mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-12 10:27:39 +00:00
BLE RX/TX Changes (#2752)
* Work on BLE Rx Tx improvements. * Working on compile size. * cleanup * Formatting * Fixes * More Improvements + Custom Parsing for Tags * Moving ERT to external apps. * Fix Icon.
This commit is contained in:
@@ -270,11 +270,9 @@ set(CPPSRC
|
|||||||
ui/ui_bmpview.cpp
|
ui/ui_bmpview.cpp
|
||||||
apps/ais_app.cpp
|
apps/ais_app.cpp
|
||||||
apps/analog_audio_app.cpp
|
apps/analog_audio_app.cpp
|
||||||
apps/ble_comm_app.cpp
|
|
||||||
apps/ble_rx_app.cpp
|
apps/ble_rx_app.cpp
|
||||||
apps/ble_tx_app.cpp
|
apps/ble_tx_app.cpp
|
||||||
apps/capture_app.cpp
|
apps/capture_app.cpp
|
||||||
apps/ert_app.cpp
|
|
||||||
apps/pocsag_app.cpp
|
apps/pocsag_app.cpp
|
||||||
apps/soundboard_app.cpp
|
apps/soundboard_app.cpp
|
||||||
apps/ui_about_simple.cpp
|
apps/ui_about_simple.cpp
|
||||||
|
@@ -69,7 +69,7 @@ static std::uint64_t get_freq_by_channel_number(uint8_t channel_number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLECommView::focus() {
|
void BLECommView::focus() {
|
||||||
options_channel.focus();
|
field_frequency.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
BLECommView::BLECommView(NavigationView& nav)
|
BLECommView::BLECommView(NavigationView& nav)
|
||||||
@@ -79,10 +79,7 @@ BLECommView::BLECommView(NavigationView& nav)
|
|||||||
&field_rf_amp,
|
&field_rf_amp,
|
||||||
&field_lna,
|
&field_lna,
|
||||||
&field_vga,
|
&field_vga,
|
||||||
&options_channel,
|
|
||||||
&field_frequency,
|
&field_frequency,
|
||||||
&label_send_adv,
|
|
||||||
&button_send_adv,
|
|
||||||
&check_log,
|
&check_log,
|
||||||
&label_packets_sent,
|
&label_packets_sent,
|
||||||
&text_packets_sent,
|
&text_packets_sent,
|
||||||
@@ -90,10 +87,6 @@ BLECommView::BLECommView(NavigationView& nav)
|
|||||||
|
|
||||||
field_frequency.set_step(0);
|
field_frequency.set_step(0);
|
||||||
|
|
||||||
button_send_adv.on_select = [this](ImageButton&) {
|
|
||||||
this->toggle();
|
|
||||||
};
|
|
||||||
|
|
||||||
check_log.set_value(logging);
|
check_log.set_value(logging);
|
||||||
|
|
||||||
check_log.on_select = [this](Checkbox&, bool v) {
|
check_log.on_select = [this](Checkbox&, bool v) {
|
||||||
@@ -104,27 +97,8 @@ BLECommView::BLECommView(NavigationView& nav)
|
|||||||
logger->append(logs_dir.string() + "/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
|
logger->append(logs_dir.string() + "/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
|
||||||
};
|
};
|
||||||
|
|
||||||
options_channel.on_change = [this](size_t, int32_t i) {
|
|
||||||
// If we selected Auto don't do anything and Auto will handle changing.
|
|
||||||
if (i == 40) {
|
|
||||||
auto_channel = true;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
auto_channel = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
field_frequency.set_value(get_freq_by_channel_number(i));
|
|
||||||
channel_number_rx = i;
|
|
||||||
channel_number_tx = i;
|
|
||||||
};
|
|
||||||
|
|
||||||
options_channel.set_selected_index(3, true);
|
|
||||||
|
|
||||||
logger = std::make_unique<BLECommLogger>();
|
logger = std::make_unique<BLECommLogger>();
|
||||||
|
|
||||||
// Generate new random Mac Address upon each new startup.
|
|
||||||
generateRandomMacAddress(randomMac);
|
|
||||||
|
|
||||||
// Setup Initial Advertise Packet.
|
// Setup Initial Advertise Packet.
|
||||||
advertisePacket = build_adv_packet();
|
advertisePacket = build_adv_packet();
|
||||||
}
|
}
|
||||||
@@ -145,86 +119,66 @@ bool BLECommView::in_tx_mode() const {
|
|||||||
return (bool)is_running_tx;
|
return (bool)is_running_tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLECommView::toggle() {
|
|
||||||
if (in_tx_mode()) {
|
|
||||||
sendAdvertisement(false);
|
|
||||||
} else {
|
|
||||||
sendAdvertisement(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BLETxPacket BLECommView::build_adv_packet() {
|
BLETxPacket BLECommView::build_adv_packet() {
|
||||||
BLETxPacket bleTxPacket;
|
BLETxPacket bleTxPacket;
|
||||||
memset(&bleTxPacket, 0, sizeof(BLETxPacket));
|
memset(&bleTxPacket, 0, sizeof(BLETxPacket));
|
||||||
|
|
||||||
std::string dataString = "11094861636b524620506f7274617061636b";
|
std::string dataString = "02010603030F1807084861636B5246";
|
||||||
|
|
||||||
strncpy(bleTxPacket.macAddress, randomMac, 12);
|
|
||||||
strncpy(bleTxPacket.advertisementData, dataString.c_str(), dataString.length());
|
strncpy(bleTxPacket.advertisementData, dataString.c_str(), dataString.length());
|
||||||
|
|
||||||
// Duty cycle of 40% per 100ms advertisment periods.
|
strncpy(bleTxPacket.packetCount, "1", 2);
|
||||||
strncpy(bleTxPacket.packetCount, "80", 3);
|
bleTxPacket.packet_count = 1;
|
||||||
bleTxPacket.packet_count = 80;
|
|
||||||
|
|
||||||
bleTxPacket.packetType = PKT_TYPE_DISCOVERY;
|
bleTxPacket.pduType = PKT_TYPE_ADV_IND;
|
||||||
|
|
||||||
return bleTxPacket;
|
return bleTxPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLECommView::sendAdvertisement(bool enable) {
|
void BLECommView::sendAdvertisement(void) {
|
||||||
if (enable) {
|
|
||||||
startTx(advertisePacket);
|
startTx(advertisePacket);
|
||||||
is_adv = true;
|
ble_state = Ble_State_Advertising;
|
||||||
} else {
|
|
||||||
is_adv = false;
|
|
||||||
stopTx();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLECommView::startTx(BLETxPacket packetToSend) {
|
void BLECommView::startTx(BLETxPacket packetToSend) {
|
||||||
int randomChannel = channel_number_tx;
|
|
||||||
|
|
||||||
if (auto_channel) {
|
|
||||||
int min = 37;
|
|
||||||
int max = 39;
|
|
||||||
|
|
||||||
randomChannel = min + std::rand() % (max - min + 1);
|
|
||||||
|
|
||||||
field_frequency.set_value(get_freq_by_channel_number(randomChannel));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_tx_mode()) {
|
|
||||||
switch_rx_tx(false);
|
switch_rx_tx(false);
|
||||||
|
|
||||||
currentPacket = packetToSend;
|
currentPacket = packetToSend;
|
||||||
packet_counter = currentPacket.packet_count;
|
packet_counter = currentPacket.packet_count;
|
||||||
|
|
||||||
button_send_adv.set_bitmap(&bitmap_stop);
|
switch (advCount) {
|
||||||
baseband::set_btletx(randomChannel, currentPacket.macAddress, currentPacket.advertisementData, currentPacket.packetType);
|
case 0:
|
||||||
|
channel_number_tx = 37;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
channel_number_tx = 38;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
channel_number_tx = 39;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_frequency.set_value(get_freq_by_channel_number(37));
|
||||||
|
|
||||||
|
advCount++;
|
||||||
|
|
||||||
|
if (advCount == 3) {
|
||||||
|
advCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseband::set_btletx(37, deviceMAC, currentPacket.advertisementData, currentPacket.pduType);
|
||||||
transmitter_model.set_tx_gain(47);
|
transmitter_model.set_tx_gain(47);
|
||||||
transmitter_model.enable();
|
transmitter_model.enable();
|
||||||
|
|
||||||
is_running_tx = true;
|
is_running_tx = true;
|
||||||
} else {
|
|
||||||
baseband::set_btletx(randomChannel, currentPacket.macAddress, currentPacket.advertisementData, currentPacket.packetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((packet_counter % 10) == 0) {
|
|
||||||
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
|
||||||
}
|
|
||||||
|
|
||||||
is_sending = true;
|
|
||||||
|
|
||||||
packet_counter--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLECommView::stopTx() {
|
void BLECommView::stopTx() {
|
||||||
button_send_adv.set_bitmap(&bitmap_play);
|
|
||||||
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
||||||
|
|
||||||
switch_rx_tx(true);
|
switch_rx_tx(true);
|
||||||
|
|
||||||
baseband::set_btlerx(channel_number_rx);
|
baseband::set_btlerx(channel_number_rx);
|
||||||
|
field_frequency.set_value(get_freq_by_channel_number(channel_number_rx));
|
||||||
receiver_model.enable();
|
receiver_model.enable();
|
||||||
|
|
||||||
is_running_tx = false;
|
is_running_tx = false;
|
||||||
@@ -248,14 +202,12 @@ void BLECommView::on_data(BlePacketData* packet) {
|
|||||||
parse_received_packet(packet, (ADV_PDU_TYPE)packet->type);
|
parse_received_packet(packet, (ADV_PDU_TYPE)packet->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called each 1/60th of second, so 6 = 100ms
|
|
||||||
void BLECommView::on_timer() {
|
void BLECommView::on_timer() {
|
||||||
// Send advertise burst only once every 100ms
|
|
||||||
if (++timer_counter == timer_period) {
|
if (++timer_counter == timer_period) {
|
||||||
timer_counter = 0;
|
timer_counter = 0;
|
||||||
|
|
||||||
if (!is_adv) {
|
if (ble_state == Ble_State_Receiving || ble_state == Ble_State_Idle) {
|
||||||
sendAdvertisement(true);
|
sendAdvertisement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,17 +215,18 @@ void BLECommView::on_timer() {
|
|||||||
void BLECommView::on_tx_progress(const bool done) {
|
void BLECommView::on_tx_progress(const bool done) {
|
||||||
if (done) {
|
if (done) {
|
||||||
if (in_tx_mode()) {
|
if (in_tx_mode()) {
|
||||||
is_sending = false;
|
ble_state = Ble_State_Receiving;
|
||||||
|
|
||||||
|
timer_counter = 0;
|
||||||
|
timer_period = 12;
|
||||||
|
|
||||||
if (packet_counter == 0) {
|
|
||||||
if (is_adv) {
|
|
||||||
sendAdvertisement(false);
|
|
||||||
} else {
|
|
||||||
stopTx();
|
stopTx();
|
||||||
}
|
|
||||||
} else {
|
// else
|
||||||
startTx(currentPacket);
|
// {
|
||||||
}
|
// startTx(advertisePacket);
|
||||||
|
// advCount++;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,23 +262,28 @@ void BLECommView::parse_received_packet(const BlePacketData* packet, ADV_PDU_TYP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pdu_type == SCAN_REQ || pdu_type == CONNECT_REQ) {
|
if (pdu_type == SCAN_REQ || pdu_type == CONNECT_REQ) {
|
||||||
|
if (pdu_type == SCAN_REQ) {
|
||||||
ADV_PDU_PAYLOAD_TYPE_1_3* directed_mac_data = (ADV_PDU_PAYLOAD_TYPE_1_3*)packet->data;
|
ADV_PDU_PAYLOAD_TYPE_1_3* directed_mac_data = (ADV_PDU_PAYLOAD_TYPE_1_3*)packet->data;
|
||||||
|
|
||||||
std::reverse(directed_mac_data->A1, directed_mac_data->A1 + 6);
|
std::reverse(directed_mac_data->A1, directed_mac_data->A1 + 6);
|
||||||
console.clear(true);
|
std::string directedMAC = to_string_mac_address(directed_mac_data->A1, 6, false);
|
||||||
std::string str_console = "";
|
|
||||||
std::string pduTypeStr = "";
|
|
||||||
|
|
||||||
if (pdu_type == SCAN_REQ) {
|
// Compare directed MAC Hex with the device MAC.
|
||||||
pduTypeStr += "SCAN_REQ";
|
if (1) {
|
||||||
} else if (pdu_type == CONNECT_REQ) {
|
// std::string str_console = "Received SCAN_REQ from directed MAC: " + directedMAC + "\n";
|
||||||
pduTypeStr += "CONNECT_REQ";
|
// console.clear(true);
|
||||||
|
// console.writeln(str_console);
|
||||||
}
|
}
|
||||||
|
} else if (pdu_type == CONNECT_REQ) {
|
||||||
|
ADV_PDU_PAYLOAD_TYPE_5* connectReq = (ADV_PDU_PAYLOAD_TYPE_5*)packet->data;
|
||||||
|
|
||||||
str_console += "PACKET TYPE:" + pduTypeStr + "\n";
|
std::reverse(connectReq->AdvA, connectReq->AdvA + 6);
|
||||||
str_console += "MY MAC:" + to_string_formatted_mac_address(randomMac) + "\n";
|
std::string directedMAC = to_string_mac_address(connectReq->AdvA, 6, false);
|
||||||
str_console += "SCAN MAC:" + to_string_mac_address(directed_mac_data->A1, 6, false) + "\n";
|
|
||||||
console.write(str_console);
|
std::string str_console = "Received CONNECT_REQ from directed MAC: " + directedMAC + "\n";
|
||||||
|
console.clear(true);
|
||||||
|
console.writeln(str_console);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,7 +76,16 @@ class BLECommView : public View {
|
|||||||
void on_data(BlePacketData* packetData);
|
void on_data(BlePacketData* packetData);
|
||||||
void on_tx_progress(const bool done);
|
void on_tx_progress(const bool done);
|
||||||
void parse_received_packet(const BlePacketData* packet, ADV_PDU_TYPE pdu_type);
|
void parse_received_packet(const BlePacketData* packet, ADV_PDU_TYPE pdu_type);
|
||||||
void sendAdvertisement(bool enable);
|
void sendAdvertisement(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Ble_State_Idle = 0,
|
||||||
|
Ble_State_Advertising = 1,
|
||||||
|
Ble_State_Receiving = 2,
|
||||||
|
Ble_State_Sending = 3
|
||||||
|
} BleState;
|
||||||
|
|
||||||
|
BleState ble_state{Ble_State_Idle};
|
||||||
|
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
@@ -101,8 +110,9 @@ class BLECommView : public View {
|
|||||||
uint8_t channel_number_tx = 37;
|
uint8_t channel_number_tx = 37;
|
||||||
uint8_t channel_number_rx = 37;
|
uint8_t channel_number_rx = 37;
|
||||||
bool auto_channel = false;
|
bool auto_channel = false;
|
||||||
|
uint8_t advCount = 0;
|
||||||
|
|
||||||
char randomMac[13] = "010203040506";
|
char deviceMAC[13] = "C23456789ABC";
|
||||||
|
|
||||||
bool is_running_tx = false;
|
bool is_running_tx = false;
|
||||||
bool is_sending = false;
|
bool is_sending = false;
|
||||||
@@ -111,7 +121,7 @@ class BLECommView : public View {
|
|||||||
int16_t timer_period{6}; // Delay each packet by 16ms.
|
int16_t timer_period{6}; // Delay each packet by 16ms.
|
||||||
int16_t timer_counter = 0;
|
int16_t timer_counter = 0;
|
||||||
int16_t timer_rx_counter = 0;
|
int16_t timer_rx_counter = 0;
|
||||||
int16_t timer_rx_period{12}; // Poll Rx for at least 200ms. (TBD)
|
int16_t timer_rx_period{12}; // Poll Rx for at least 150ms. (TBD)
|
||||||
|
|
||||||
uint32_t packet_counter{0};
|
uint32_t packet_counter{0};
|
||||||
BLETxPacket advertisePacket{};
|
BLETxPacket advertisePacket{};
|
||||||
@@ -147,15 +157,6 @@ class BLECommView : public View {
|
|||||||
Channel channel{
|
Channel channel{
|
||||||
{24 * 8, 5, 6 * 8, 4}};
|
{24 * 8, 5, 6 * 8, 4}};
|
||||||
|
|
||||||
Labels label_send_adv{
|
|
||||||
{{0 * 8, 2 * 8}, "Send Advertisement:", Theme::getInstance()->fg_light->foreground}};
|
|
||||||
|
|
||||||
ImageButton button_send_adv{
|
|
||||||
{21 * 8, 1 * 16, 10 * 8, 2 * 16},
|
|
||||||
&bitmap_play,
|
|
||||||
Theme::getInstance()->fg_green->foreground,
|
|
||||||
Theme::getInstance()->fg_green->background};
|
|
||||||
|
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
{24 * 8, 2 * 8},
|
{24 * 8, 2 * 8},
|
||||||
3,
|
3,
|
||||||
|
@@ -247,7 +247,7 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl
|
|||||||
};
|
};
|
||||||
|
|
||||||
button_send.on_select = [this, &nav](const ui::Button&) {
|
button_send.on_select = [this, &nav](const ui::Button&) {
|
||||||
auto packetToSend = build_packet();
|
auto packetToSend = build_packet(entry_);
|
||||||
nav.set_on_pop([packetToSend, &nav]() {
|
nav.set_on_pop([packetToSend, &nav]() {
|
||||||
nav.replace<BLETxView>(packetToSend);
|
nav.replace<BLETxView>(packetToSend);
|
||||||
});
|
});
|
||||||
@@ -255,7 +255,7 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl
|
|||||||
};
|
};
|
||||||
|
|
||||||
button_save.on_select = [this, &nav](const ui::Button&) {
|
button_save.on_select = [this, &nav](const ui::Button&) {
|
||||||
auto packetToSave = build_packet();
|
auto packetToSave = build_packet(entry_);
|
||||||
|
|
||||||
packetFileBuffer = "";
|
packetFileBuffer = "";
|
||||||
text_prompt(
|
text_prompt(
|
||||||
@@ -436,7 +436,7 @@ void BleRecentEntryDetailView::set_entry(const BleRecentEntry& entry) {
|
|||||||
set_dirty();
|
set_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
BLETxPacket BleRecentEntryDetailView::build_packet() {
|
BLETxPacket BleRecentEntryDetailView::build_packet(BleRecentEntry entry_) {
|
||||||
BLETxPacket bleTxPacket;
|
BLETxPacket bleTxPacket;
|
||||||
memset(&bleTxPacket, 0, sizeof(BLETxPacket));
|
memset(&bleTxPacket, 0, sizeof(BLETxPacket));
|
||||||
|
|
||||||
@@ -444,8 +444,8 @@ BLETxPacket BleRecentEntryDetailView::build_packet() {
|
|||||||
|
|
||||||
strncpy(bleTxPacket.macAddress, macAddressStr.c_str(), 12);
|
strncpy(bleTxPacket.macAddress, macAddressStr.c_str(), 12);
|
||||||
strncpy(bleTxPacket.advertisementData, entry_.dataString.c_str(), entry_.packetData.dataLen * 2);
|
strncpy(bleTxPacket.advertisementData, entry_.dataString.c_str(), entry_.packetData.dataLen * 2);
|
||||||
strncpy(bleTxPacket.packetCount, "50", 3);
|
strncpy(bleTxPacket.packetCount, "10", 3);
|
||||||
bleTxPacket.packet_count = 50;
|
bleTxPacket.packet_count = 10;
|
||||||
|
|
||||||
return bleTxPacket;
|
return bleTxPacket;
|
||||||
}
|
}
|
||||||
@@ -495,16 +495,18 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
&field_vga,
|
&field_vga,
|
||||||
&options_channel,
|
&options_channel,
|
||||||
&field_frequency,
|
&field_frequency,
|
||||||
&check_log,
|
|
||||||
&button_find,
|
|
||||||
&check_name,
|
|
||||||
&label_sort,
|
&label_sort,
|
||||||
&options_sort,
|
&options_sort,
|
||||||
&label_found,
|
|
||||||
&text_found_count,
|
|
||||||
&check_serial_log,
|
|
||||||
&button_filter,
|
&button_filter,
|
||||||
&options_filter,
|
&options_filter,
|
||||||
|
&check_name,
|
||||||
|
&check_log,
|
||||||
|
&check_serial_log,
|
||||||
|
&check_unique,
|
||||||
|
&check_duplicate_packets,
|
||||||
|
&button_find,
|
||||||
|
&label_found,
|
||||||
|
&text_found_count,
|
||||||
&button_save_list,
|
&button_save_list,
|
||||||
&button_clear_list,
|
&button_clear_list,
|
||||||
&button_switch,
|
&button_switch,
|
||||||
@@ -516,6 +518,29 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
nav_.push<BleRecentEntryDetailView>(entry);
|
nav_.push<BleRecentEntryDetailView>(entry);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ensure_directory(find_packet_path);
|
||||||
|
ensure_directory(log_packets_path);
|
||||||
|
ensure_directory(packet_save_path);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Handle Check Boxes
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
logger = std::make_unique<BLELogger>();
|
||||||
|
|
||||||
|
check_name.on_select = [this](Checkbox&, bool v) {
|
||||||
|
name_enable = v;
|
||||||
|
// update the include_name instance variable value of each entry in recent entries
|
||||||
|
setAllMembersToValue(recent, &BleRecentEntry::include_name, v);
|
||||||
|
recent_entries_view.set_dirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
check_log.on_select = [this](Checkbox&, bool v) {
|
||||||
|
logging = v;
|
||||||
|
|
||||||
|
if (logger && logging)
|
||||||
|
logger->append(bletx_dir.string() + "/Packets/BLETx_" + to_string_timestamp(rtc_time::now()) + ".TXT");
|
||||||
|
};
|
||||||
|
|
||||||
check_serial_log.on_select = [this](Checkbox&, bool v) {
|
check_serial_log.on_select = [this](Checkbox&, bool v) {
|
||||||
serial_logging = v;
|
serial_logging = v;
|
||||||
if (v) {
|
if (v) {
|
||||||
@@ -524,12 +549,28 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
portapack::async_tx_enabled = false;
|
portapack::async_tx_enabled = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
check_unique.on_select = [this](Checkbox&, bool v) {
|
||||||
|
uniqueParsing = v;
|
||||||
|
recent.clear();
|
||||||
|
recent_entries_view.set_dirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
check_duplicate_packets.on_select = [this](Checkbox&, bool v) {
|
||||||
|
duplicatePackets = v;
|
||||||
|
recent.clear();
|
||||||
|
recent_entries_view.set_dirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
check_name.set_value(name_enable);
|
||||||
|
check_log.set_value(logging);
|
||||||
check_serial_log.set_value(serial_logging);
|
check_serial_log.set_value(serial_logging);
|
||||||
|
check_unique.set_value(uniqueParsing);
|
||||||
|
check_duplicate_packets.set_value(duplicatePackets);
|
||||||
|
|
||||||
ensure_directory(find_packet_path);
|
// ------------------------------------------------------------------------------
|
||||||
ensure_directory(log_packets_path);
|
// Handle Buttons
|
||||||
ensure_directory(packet_save_path);
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
filterBuffer = filter;
|
filterBuffer = filter;
|
||||||
|
|
||||||
button_filter.on_select = [this](Button&) {
|
button_filter.on_select = [this](Button&) {
|
||||||
@@ -543,16 +584,6 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
logger = std::make_unique<BLELogger>();
|
|
||||||
|
|
||||||
check_log.on_select = [this](Checkbox&, bool v) {
|
|
||||||
logging = v;
|
|
||||||
|
|
||||||
if (logger && logging)
|
|
||||||
logger->append(blerx_dir.string() + "/Logs/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
|
|
||||||
};
|
|
||||||
check_log.set_value(logging);
|
|
||||||
|
|
||||||
button_save_list.on_select = [this, &nav](const ui::Button&) {
|
button_save_list.on_select = [this, &nav](const ui::Button&) {
|
||||||
listFileBuffer = "";
|
listFileBuffer = "";
|
||||||
text_prompt(
|
text_prompt(
|
||||||
@@ -574,16 +605,17 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
nav.replace<BLETxView>();
|
nav.replace<BLETxView>();
|
||||||
};
|
};
|
||||||
|
|
||||||
field_frequency.set_step(0);
|
button_find.on_select = [this](Button&) {
|
||||||
|
auto open_view = nav_.push<FileLoadView>(".TXT");
|
||||||
check_name.set_value(name_enable);
|
open_view->on_changed = [this](std::filesystem::path new_file_path) {
|
||||||
|
on_file_changed(new_file_path);
|
||||||
check_name.on_select = [this](Checkbox&, bool v) {
|
|
||||||
name_enable = v;
|
|
||||||
// update the include_name instance variable value of each entry in recent entries
|
|
||||||
setAllMembersToValue(recent, &BleRecentEntry::include_name, v);
|
|
||||||
recent_entries_view.set_dirty();
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Handle Options
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
field_frequency.set_step(0);
|
||||||
|
|
||||||
options_channel.on_change = [this](size_t index, int32_t v) {
|
options_channel.on_change = [this](size_t index, int32_t v) {
|
||||||
channel_index = (uint8_t)index;
|
channel_index = (uint8_t)index;
|
||||||
@@ -611,7 +643,6 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
filter_index = (uint8_t)index;
|
filter_index = (uint8_t)index;
|
||||||
recent.clear();
|
recent.clear();
|
||||||
handle_filter_options(v);
|
handle_filter_options(v);
|
||||||
uniqueParsing = filter_index == 2 ? true : false;
|
|
||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -619,15 +650,6 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
options_sort.set_selected_index(sort_index, true);
|
options_sort.set_selected_index(sort_index, true);
|
||||||
options_filter.set_selected_index(filter_index, true);
|
options_filter.set_selected_index(filter_index, true);
|
||||||
|
|
||||||
button_find.on_select = [this](Button&) {
|
|
||||||
auto open_view = nav_.push<FileLoadView>(".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)
|
// Auto-configure modem for LCR RX (will be removed later)
|
||||||
baseband::set_btlerx(channel_number);
|
baseband::set_btlerx(channel_number);
|
||||||
|
|
||||||
@@ -785,12 +807,17 @@ bool BLERxView::saveFile(const std::filesystem::path& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLERxView::on_data(BlePacketData* packet) {
|
void BLERxView::on_data(BlePacketData* packet) {
|
||||||
uint64_t macAddressEncoded = copy_mac_address_to_uint64(packet->macAddress);
|
uint64_t uniqueKeyEncoded = copy_mac_address_to_uint64(packet->macAddress);
|
||||||
|
|
||||||
// Start of Packet stuffing.
|
// Start of Packet stuffing.
|
||||||
// Masking off the top 2 bytes to avoid invalid keys.
|
// Masking off the top 2 bytes to avoid invalid keys.
|
||||||
|
|
||||||
uint64_t key = macAddressEncoded & 0xFFFFFFFFFFFF;
|
uint64_t key = (uniqueKeyEncoded & 0xFFFFFFFFFFFF);
|
||||||
|
|
||||||
|
if (duplicatePackets) {
|
||||||
|
key |= ((uint64_t)packet->type) << 48;
|
||||||
|
}
|
||||||
|
|
||||||
bool packetExists = false;
|
bool packetExists = false;
|
||||||
|
|
||||||
// If found store into tempEntry to modify.
|
// If found store into tempEntry to modify.
|
||||||
@@ -866,10 +893,6 @@ void BLERxView::log_ble_packet(BlePacketData* packet) {
|
|||||||
void BLERxView::on_filter_change(std::string value) {
|
void BLERxView::on_filter_change(std::string value) {
|
||||||
// New filter? Reset list from recent entries.
|
// New filter? Reset list from recent entries.
|
||||||
if (filter != value) {
|
if (filter != value) {
|
||||||
// resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
|
||||||
// // return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
|
||||||
// return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos) && (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
|
||||||
// });
|
|
||||||
filter = value;
|
filter = value;
|
||||||
handle_filter_options(options_filter.selected_index());
|
handle_filter_options(options_filter.selected_index());
|
||||||
}
|
}
|
||||||
@@ -947,7 +970,7 @@ void BLERxView::handle_entries_sort(uint8_t index) {
|
|||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
sortEntriesBy(
|
sortEntriesBy(
|
||||||
recent, [](const BleRecentEntry& entry) { return entry.macAddress; }, true);
|
recent, [](const BleRecentEntry& entry) { return entry.uniqueKey & 0xFFFFFFFFFFFF; }, true);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
sortEntriesBy(
|
sortEntriesBy(
|
||||||
@@ -965,6 +988,10 @@ void BLERxView::handle_entries_sort(uint8_t index) {
|
|||||||
sortEntriesBy(
|
sortEntriesBy(
|
||||||
recent, [](const BleRecentEntry& entry) { return entry.nameString; }, true);
|
recent, [](const BleRecentEntry& entry) { return entry.nameString; }, true);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
sortEntriesBy(
|
||||||
|
recent, [](const BleRecentEntry& entry) { return entry.informationString; }, true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -975,16 +1002,43 @@ void BLERxView::handle_entries_sort(uint8_t index) {
|
|||||||
void BLERxView::handle_filter_options(uint8_t index) {
|
void BLERxView::handle_filter_options(uint8_t index) {
|
||||||
auto value = filter;
|
auto value = filter;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: // filter by Data
|
// Data
|
||||||
|
case 0:
|
||||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 1: // filter by MAC address (All caps: e.g. AA:BB:CC:DD:EE:FF)
|
// MAC address (All caps: e.g. AA:BB:CC:DD:EE:FF)
|
||||||
|
case 1:
|
||||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
return (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
return (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
// Name
|
||||||
|
case 2:
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
return (entry.nameString.find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// Info
|
||||||
|
case 3:
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
return (entry.informationString.find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// Vendor
|
||||||
|
case 4:
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
std::string vendor_name = lookup_mac_vendor(entry.packetData.macAddress);
|
||||||
|
return (vendor_name.find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// Channel
|
||||||
|
case 5:
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
return (to_string_dec_int(entry.channelNumber).find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1007,6 +1061,24 @@ bool BLERxView::updateEntry(const BlePacketData* packet, BleRecentEntry& entry,
|
|||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
// Only parse name for advertisment packets and empty name entries
|
||||||
|
if (pdu_type == ADV_IND || pdu_type == ADV_NONCONN_IND || pdu_type == SCAN_RSP || pdu_type == ADV_SCAN_IND) {
|
||||||
|
if (uniqueParsing) {
|
||||||
|
success = parse_tracking_beacon_data(packet->data, packet->dataLen, entry.nameString, entry.informationString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success && !uniqueParsing) {
|
||||||
|
success = parse_beacon_data(packet->data, packet->dataLen, entry.nameString, entry.informationString);
|
||||||
|
}
|
||||||
|
} else if (pdu_type == ADV_DIRECT_IND || pdu_type == SCAN_REQ) {
|
||||||
|
if (!uniqueParsing) {
|
||||||
|
ADV_PDU_PAYLOAD_TYPE_1_3* directed_mac_data = (ADV_PDU_PAYLOAD_TYPE_1_3*)packet->data;
|
||||||
|
reverse_byte_array(directed_mac_data->A1, 6);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < packet->dataLen; i++) {
|
for (i = 0; i < packet->dataLen; i++) {
|
||||||
@@ -1044,25 +1116,123 @@ bool BLERxView::updateEntry(const BlePacketData* packet, BleRecentEntry& entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry.include_name = check_name.value();
|
entry.include_name = check_name.value();
|
||||||
|
|
||||||
// Only parse name for advertisment packets and empty name entries
|
|
||||||
if (pdu_type == ADV_IND || pdu_type == ADV_NONCONN_IND || pdu_type == SCAN_RSP || pdu_type == ADV_SCAN_IND) {
|
|
||||||
if (uniqueParsing) {
|
|
||||||
// Add your unique beacon parsing function here.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success && !uniqueParsing) {
|
|
||||||
success = parse_beacon_data(packet->data, packet->dataLen, entry.nameString, entry.informationString);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (pdu_type == ADV_DIRECT_IND || pdu_type == SCAN_REQ) {
|
|
||||||
ADV_PDU_PAYLOAD_TYPE_1_3* directed_mac_data = (ADV_PDU_PAYLOAD_TYPE_1_3*)entry.packetData.data;
|
|
||||||
reverse_byte_array(directed_mac_data->A1, 6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BLERxView::parse_tracking_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString) {
|
||||||
|
uint8_t currentByte, currentLength, currentType = 0;
|
||||||
|
|
||||||
|
for (currentByte = 0; currentByte < length;) {
|
||||||
|
currentLength = data[currentByte++];
|
||||||
|
currentType = data[currentByte++];
|
||||||
|
|
||||||
|
// Manufacturer Specific Data (0xFF)
|
||||||
|
if (currentType == 0xFF && currentLength >= 4) {
|
||||||
|
uint16_t companyID = data[currentByte] | (data[currentByte + 1] << 8);
|
||||||
|
|
||||||
|
// Apple AirTag / Find My
|
||||||
|
if (companyID == 0x004C && currentLength >= 6) {
|
||||||
|
uint8_t appleType = data[currentByte + 2];
|
||||||
|
uint8_t appleLen = data[currentByte + 3];
|
||||||
|
if (appleType == 0x12 && appleLen == 0x19 && currentLength >= 4 + appleLen) {
|
||||||
|
nameString.assign("Apple AirTag");
|
||||||
|
informationString.assign("Find My");
|
||||||
|
return true;
|
||||||
|
} else if (appleType == 0x02 && appleLen == 0x15) {
|
||||||
|
uint16_t major = (data[currentByte + 20] << 8) | data[currentByte + 21];
|
||||||
|
uint16_t minor = (data[currentByte + 22] << 8) | data[currentByte + 23];
|
||||||
|
|
||||||
|
nameString.assign("iBeacon");
|
||||||
|
informationString.assign(to_string_hex(major) + to_string_hex(minor));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Services
|
||||||
|
else if ((currentType == 0x02 || currentType == 0x03) && currentLength >= 3) {
|
||||||
|
for (int u = 0; u < currentLength - 1; u += 2) {
|
||||||
|
uint16_t uuid16 = data[currentByte + u] | (data[currentByte + u + 1] << 8);
|
||||||
|
if (uuid16 == 0x1802) { // Immediate Alert Service = Find Me Profile
|
||||||
|
nameString.assign("FindMe");
|
||||||
|
informationString.assign("IAS");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Service Data
|
||||||
|
else if (currentType == 0x16 && currentLength >= 3) {
|
||||||
|
uint16_t uuid16 = data[currentByte] | (data[currentByte + 1] << 8);
|
||||||
|
|
||||||
|
switch (uuid16) {
|
||||||
|
case 0xFD59: { // Samsung SmartTag - Unregistered
|
||||||
|
nameString.assign("Samsung SmartTag");
|
||||||
|
informationString.assign("Unreg");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 0xFD5A: { // Samsung SmartTag - Registered
|
||||||
|
nameString.assign("Samsung SmartTag");
|
||||||
|
informationString.assign("Reg");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 0xFD84: {
|
||||||
|
if (currentByte + 2 < length) {
|
||||||
|
uint8_t model = data[currentByte + 2];
|
||||||
|
switch (model) {
|
||||||
|
case 0x01:
|
||||||
|
informationString.assign("Mate");
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
informationString.assign("Pro");
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
informationString.assign("Slim");
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
informationString.assign("Sticker");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
informationString.assign("Unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nameString.assign("Tile");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 0xFEAA: {
|
||||||
|
if (currentByte + 2 < length) {
|
||||||
|
uint8_t frameType = data[currentByte + 2];
|
||||||
|
switch (frameType) {
|
||||||
|
case 0x00:
|
||||||
|
informationString.assign("UID");
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
informationString.assign("URL");
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
informationString.assign("TLM");
|
||||||
|
break;
|
||||||
|
case 0x30:
|
||||||
|
informationString.assign("EID");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
informationString.assign("Unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nameString.assign("Eddystone");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentByte += (currentLength - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool BLERxView::parse_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString) {
|
bool BLERxView::parse_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString) {
|
||||||
uint8_t currentByte, currentLength, currentType = 0;
|
uint8_t currentByte, currentLength, currentType = 0;
|
||||||
std::string tempName = "";
|
std::string tempName = "";
|
||||||
|
@@ -71,7 +71,8 @@ typedef enum {
|
|||||||
RESERVED5 = 12,
|
RESERVED5 = 12,
|
||||||
RESERVED6 = 13,
|
RESERVED6 = 13,
|
||||||
RESERVED7 = 14,
|
RESERVED7 = 14,
|
||||||
RESERVED8 = 15
|
RESERVED8 = 15,
|
||||||
|
UNKNOWN = 16
|
||||||
} ADV_PDU_TYPE;
|
} ADV_PDU_TYPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -84,9 +85,9 @@ typedef enum {
|
|||||||
struct BleRecentEntry {
|
struct BleRecentEntry {
|
||||||
using Key = uint64_t;
|
using Key = uint64_t;
|
||||||
|
|
||||||
static constexpr Key invalid_key = 0xFFFFFFFFFFFF;
|
static constexpr Key invalid_key = 0xFFFFFFFFFFFFF;
|
||||||
|
|
||||||
uint64_t macAddress;
|
uint64_t uniqueKey;
|
||||||
int dbValue;
|
int dbValue;
|
||||||
BlePacketData packetData;
|
BlePacketData packetData;
|
||||||
std::string timestamp;
|
std::string timestamp;
|
||||||
@@ -105,8 +106,8 @@ struct BleRecentEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BleRecentEntry(
|
BleRecentEntry(
|
||||||
const uint64_t macAddress)
|
const uint64_t uniqueKey)
|
||||||
: macAddress{macAddress},
|
: uniqueKey{uniqueKey},
|
||||||
dbValue{},
|
dbValue{},
|
||||||
packetData{},
|
packetData{},
|
||||||
timestamp{},
|
timestamp{},
|
||||||
@@ -122,7 +123,7 @@ struct BleRecentEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Key key() const {
|
Key key() const {
|
||||||
return macAddress;
|
return uniqueKey;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -139,11 +140,11 @@ class BleRecentEntryDetailView : public View {
|
|||||||
void update_data();
|
void update_data();
|
||||||
void focus() override;
|
void focus() override;
|
||||||
void paint(Painter&) override;
|
void paint(Painter&) override;
|
||||||
|
static BLETxPacket build_packet(BleRecentEntry entry_);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
BleRecentEntry entry_{};
|
BleRecentEntry entry_{};
|
||||||
BLETxPacket build_packet();
|
|
||||||
void on_save_file(const std::string value, BLETxPacket packetToSave);
|
void on_save_file(const std::string value, BLETxPacket packetToSave);
|
||||||
bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave);
|
bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave);
|
||||||
std::string packetFileBuffer{};
|
std::string packetFileBuffer{};
|
||||||
@@ -227,6 +228,7 @@ class BLERxView : public View {
|
|||||||
void handle_filter_options(uint8_t index);
|
void handle_filter_options(uint8_t index);
|
||||||
bool updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type);
|
bool updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type);
|
||||||
bool parse_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString);
|
bool parse_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString);
|
||||||
|
bool parse_tracking_beacon_data(const uint8_t* data, uint8_t length, std::string& nameString, std::string& informationString);
|
||||||
|
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
@@ -240,6 +242,7 @@ class BLERxView : public View {
|
|||||||
uint8_t sort_index{0};
|
uint8_t sort_index{0};
|
||||||
uint8_t filter_index{0};
|
uint8_t filter_index{0};
|
||||||
bool uniqueParsing = false;
|
bool uniqueParsing = false;
|
||||||
|
bool duplicatePackets = false;
|
||||||
std::string filter{};
|
std::string filter{};
|
||||||
bool logging{false};
|
bool logging{false};
|
||||||
bool serial_logging{false};
|
bool serial_logging{false};
|
||||||
@@ -258,6 +261,8 @@ class BLERxView : public View {
|
|||||||
// disabled to always start without USB serial activated until we can make it non blocking if not connected
|
// disabled to always start without USB serial activated until we can make it non blocking if not connected
|
||||||
// {"serial_log"sv, &serial_logging},
|
// {"serial_log"sv, &serial_logging},
|
||||||
{"name"sv, &name_enable},
|
{"name"sv, &name_enable},
|
||||||
|
{"unique_parsing"sv, &uniqueParsing},
|
||||||
|
{"duplicate_packets"sv, &duplicatePackets},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
std::string str_console = "";
|
std::string str_console = "";
|
||||||
@@ -267,7 +272,7 @@ class BLERxView : public View {
|
|||||||
bool auto_channel = false;
|
bool auto_channel = false;
|
||||||
|
|
||||||
int16_t timer_count{0};
|
int16_t timer_count{0};
|
||||||
int16_t timer_period{2}; // 25ms
|
int16_t timer_period{1}; // 25ms
|
||||||
|
|
||||||
std::string filterBuffer{};
|
std::string filterBuffer{};
|
||||||
std::string listFileBuffer{};
|
std::string listFileBuffer{};
|
||||||
@@ -283,7 +288,7 @@ class BLERxView : public View {
|
|||||||
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
|
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
|
||||||
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
|
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
|
||||||
|
|
||||||
static constexpr auto header_height = 9 * 8;
|
static constexpr auto header_height = 12 * 8;
|
||||||
static constexpr auto switch_button_height = 3 * 16;
|
static constexpr auto switch_button_height = 3 * 16;
|
||||||
|
|
||||||
OptionsField options_channel{
|
OptionsField options_channel{
|
||||||
@@ -323,7 +328,8 @@ class BLERxView : public View {
|
|||||||
{"Hits", 1},
|
{"Hits", 1},
|
||||||
{"dB", 2},
|
{"dB", 2},
|
||||||
{"Time", 3},
|
{"Time", 3},
|
||||||
{"Name", 4}}};
|
{"Name", 4},
|
||||||
|
{"Info", 5}}};
|
||||||
|
|
||||||
Button button_filter{
|
Button button_filter{
|
||||||
{11 * 8, 2 * 8, 7 * 8, 16},
|
{11 * 8, 2 * 8, 7 * 8, 16},
|
||||||
@@ -334,7 +340,10 @@ class BLERxView : public View {
|
|||||||
7,
|
7,
|
||||||
{{"Data", 0},
|
{{"Data", 0},
|
||||||
{"MAC", 1},
|
{"MAC", 1},
|
||||||
{"Unique", 2}}};
|
{"Name", 2},
|
||||||
|
{"Info", 3},
|
||||||
|
{"Vendor", 4},
|
||||||
|
{"Channel", 5}}};
|
||||||
|
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
{10 * 8, 4 * 8 + 2},
|
{10 * 8, 4 * 8 + 2},
|
||||||
@@ -348,36 +357,45 @@ class BLERxView : public View {
|
|||||||
"Name",
|
"Name",
|
||||||
true};
|
true};
|
||||||
|
|
||||||
Button button_find{
|
|
||||||
{0 * 8, 7 * 8 - 2, 4 * 8, 16},
|
|
||||||
"Find"};
|
|
||||||
|
|
||||||
Labels label_found{
|
|
||||||
{{5 * 8, 7 * 8 - 2}, "Found:", Theme::getInstance()->fg_light->foreground}};
|
|
||||||
|
|
||||||
Text text_found_count{
|
|
||||||
{11 * 8, 7 * 8 - 2, 20 * 8, 16},
|
|
||||||
"0/0"};
|
|
||||||
|
|
||||||
Checkbox check_serial_log{
|
Checkbox check_serial_log{
|
||||||
{18 * 8 + 2, 4 * 8 + 2},
|
{18 * 8 + 2, 4 * 8 + 2},
|
||||||
7,
|
7,
|
||||||
"USB Log",
|
"USB Log",
|
||||||
true};
|
true};
|
||||||
|
|
||||||
// Console console{
|
Checkbox check_unique{
|
||||||
// {0, 10 * 8, screen_height, screen_height-80}};
|
{0 * 8 + 2, 7 * 8 + 2},
|
||||||
|
7,
|
||||||
|
"Unique",
|
||||||
|
true};
|
||||||
|
|
||||||
|
Checkbox check_duplicate_packets{
|
||||||
|
{10 * 8 + 2, 7 * 8 + 2},
|
||||||
|
7,
|
||||||
|
"Duplicate",
|
||||||
|
true};
|
||||||
|
|
||||||
|
Button button_find{
|
||||||
|
{0 * 8, 10 * 8 - 2, 4 * 8, 16},
|
||||||
|
"Find"};
|
||||||
|
|
||||||
|
Labels label_found{
|
||||||
|
{{5 * 8, 10 * 8 - 2}, "Found:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
|
Text text_found_count{
|
||||||
|
{11 * 8, 10 * 8 - 2, 20 * 8, 16},
|
||||||
|
"0/0"};
|
||||||
|
|
||||||
Button button_clear_list{
|
Button button_clear_list{
|
||||||
{2 * 8, screen_height - (16 + 32), 7 * 8, 32},
|
{2 * 8, 320 - (16 + 32), 7 * 8, 32},
|
||||||
"Clear"};
|
"Clear"};
|
||||||
|
|
||||||
Button button_save_list{
|
Button button_save_list{
|
||||||
{11 * 8, screen_height - (16 + 32), 11 * 8, 32},
|
{11 * 8, 320 - (16 + 32), 11 * 8, 32},
|
||||||
"Export CSV"};
|
"Export CSV"};
|
||||||
|
|
||||||
Button button_switch{
|
Button button_switch{
|
||||||
{screen_width - 6 * 8, screen_height - (16 + 32), 4 * 8, 32},
|
{240 - 6 * 8, 320 - (16 + 32), 4 * 8, 32},
|
||||||
"Tx"};
|
"Tx"};
|
||||||
|
|
||||||
std::string str_log{""};
|
std::string str_log{""};
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "rtc_time.hpp"
|
#include "rtc_time.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "file_path.hpp"
|
#include "file_path.hpp"
|
||||||
|
#include "usb_serial_asyncmsg.hpp"
|
||||||
|
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
using namespace modems;
|
using namespace modems;
|
||||||
@@ -123,6 +124,31 @@ static std::uint64_t get_freq_by_channel_number(uint8_t channel_number) {
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
PKT_TYPE get_pkt_type_from_string(const std::string& type_str) {
|
||||||
|
if (type_str == "RAW") {
|
||||||
|
return PKT_TYPE_RAW;
|
||||||
|
} else if (type_str == "DISCOVERY") {
|
||||||
|
return PKT_TYPE_DISCOVERY;
|
||||||
|
} else if (type_str == "IBEACON") {
|
||||||
|
return PKT_TYPE_IBEACON;
|
||||||
|
} else if (type_str == "ADV_IND") {
|
||||||
|
return PKT_TYPE_ADV_IND;
|
||||||
|
} else if (type_str == "ADV_DIRECT_IND") {
|
||||||
|
return PKT_TYPE_ADV_DIRECT_IND;
|
||||||
|
} else if (type_str == "ADV_NONCONN_IND") {
|
||||||
|
return PKT_TYPE_ADV_NONCONN_IND;
|
||||||
|
} else if (type_str == "ADV_SCAN_IND") {
|
||||||
|
return PKT_TYPE_ADV_SCAN_IND;
|
||||||
|
} else if (type_str == "SCAN_REQ") {
|
||||||
|
return PKT_TYPE_SCAN_REQ;
|
||||||
|
} else if (type_str == "SCAN_RSP") {
|
||||||
|
return PKT_TYPE_SCAN_RSP;
|
||||||
|
} else if (type_str == "CONNECT_REQ") {
|
||||||
|
return PKT_TYPE_CONNECT_REQ;
|
||||||
|
}
|
||||||
|
return PKT_TYPE_INVALID_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
void BLETxView::focus() {
|
void BLETxView::focus() {
|
||||||
button_open.focus();
|
button_open.focus();
|
||||||
}
|
}
|
||||||
@@ -167,28 +193,11 @@ void BLETxView::toggle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLETxView::start() {
|
void BLETxView::send_packet() {
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_btle_tx);
|
|
||||||
transmitter_model.enable();
|
|
||||||
|
|
||||||
// Generate new random Mac Address.
|
// Generate new random Mac Address.
|
||||||
|
transmitter_model.enable();
|
||||||
generateRandomMacAddress(randomMac);
|
generateRandomMacAddress(randomMac);
|
||||||
|
|
||||||
// If this is our first run, check file.
|
|
||||||
if (!is_active()) {
|
|
||||||
File data_file;
|
|
||||||
|
|
||||||
auto error = data_file.open(file_path);
|
|
||||||
if (error && !file_override) {
|
|
||||||
file_error();
|
|
||||||
check_loop.set_value(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
button_play.set_bitmap(&bitmap_stop);
|
|
||||||
is_running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
char advertisementData[63] = {0};
|
char advertisementData[63] = {0};
|
||||||
strcpy(advertisementData, packets[current_packet].advertisementData);
|
strcpy(advertisementData, packets[current_packet].advertisementData);
|
||||||
|
|
||||||
@@ -235,9 +244,28 @@ void BLETxView::start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup next packet configuration.
|
progressbar.set_value(packets[current_packet].packet_count - packet_counter);
|
||||||
progressbar.set_max(packets[current_packet].packet_count);
|
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
||||||
baseband::set_btletx(channel_number, random_mac ? randomMac : packets[current_packet].macAddress, advertisementData, pduType);
|
|
||||||
|
baseband::set_btletx(channel_number, random_mac ? randomMac : packets[current_packet].macAddress, advertisementData, packets[current_packet].pduType);
|
||||||
|
|
||||||
|
packetDone = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLETxView::start() {
|
||||||
|
if (file_path.empty()) {
|
||||||
|
file_error();
|
||||||
|
check_loop.set_value(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseband::run_image(portapack::spi_flash::image_tag_btle_tx);
|
||||||
|
transmitter_model.enable();
|
||||||
|
|
||||||
|
button_play.set_bitmap(&bitmap_stop);
|
||||||
|
is_running = true;
|
||||||
|
|
||||||
|
send_packet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLETxView::stop() {
|
void BLETxView::stop() {
|
||||||
@@ -253,19 +281,51 @@ void BLETxView::stop() {
|
|||||||
is_running = false;
|
is_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLETxView::reset() {
|
|
||||||
transmitter_model.disable();
|
|
||||||
baseband::shutdown();
|
|
||||||
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// called each 1/60th of second, so 6 = 100ms
|
// called each 1/60th of second, so 6 = 100ms
|
||||||
void BLETxView::on_timer() {
|
void BLETxView::on_timer() {
|
||||||
if (++timer_count == timer_period) {
|
if (++timer_count == timer_period) {
|
||||||
timer_count = 0;
|
timer_count = 0;
|
||||||
|
|
||||||
|
if (is_active() && packetDone) {
|
||||||
|
send_packet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLETxView::on_tx_progress(const bool done, uint32_t progress) {
|
||||||
|
if (done) {
|
||||||
if (is_active()) {
|
if (is_active()) {
|
||||||
|
transmitter_model.disable();
|
||||||
|
if (auto_channel) {
|
||||||
|
switch (advCount) {
|
||||||
|
case 0:
|
||||||
|
channel_number = 37;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
channel_number = 38;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
channel_number = 39;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_frequency.set_value(get_freq_by_channel_number(channel_number));
|
||||||
|
|
||||||
|
if (advCount == 3) {
|
||||||
|
channel_number = 37;
|
||||||
|
packet_counter--;
|
||||||
|
packetDone = true;
|
||||||
|
advCount = 0;
|
||||||
|
} else {
|
||||||
|
send_packet();
|
||||||
|
advCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
packet_counter--;
|
||||||
|
packetDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reached end of current packet repeats.
|
// Reached end of current packet repeats.
|
||||||
if (packet_counter == 0) {
|
if (packet_counter == 0) {
|
||||||
// Done sending all packets.
|
// Done sending all packets.
|
||||||
@@ -275,44 +335,13 @@ void BLETxView::on_timer() {
|
|||||||
// If looping, restart from beginning.
|
// If looping, restart from beginning.
|
||||||
if (check_loop.value()) {
|
if (check_loop.value()) {
|
||||||
update_current_packet(packets[current_packet], current_packet);
|
update_current_packet(packets[current_packet], current_packet);
|
||||||
reset();
|
|
||||||
} else {
|
} else {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current_packet++;
|
current_packet++;
|
||||||
update_current_packet(packets[current_packet], current_packet);
|
update_current_packet(packets[current_packet], current_packet);
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++auto_channel_counter == auto_channel_period) {
|
|
||||||
auto_channel_counter = 0;
|
|
||||||
|
|
||||||
if (auto_channel) {
|
|
||||||
int min = 37;
|
|
||||||
int max = 39;
|
|
||||||
|
|
||||||
channel_number = min + std::rand() % (max - min + 1);
|
|
||||||
|
|
||||||
field_frequency.set_value(get_freq_by_channel_number(channel_number));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLETxView::on_tx_progress(const bool done) {
|
|
||||||
if (done) {
|
|
||||||
if (is_active()) {
|
|
||||||
if ((packet_counter % 10) == 0) {
|
|
||||||
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_counter--;
|
|
||||||
progressbar.set_value(packets[current_packet].packet_count - packet_counter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,7 +360,6 @@ BLETxView::BLETxView(NavigationView& nav)
|
|||||||
&label_speed,
|
&label_speed,
|
||||||
&options_speed,
|
&options_speed,
|
||||||
&options_channel,
|
&options_channel,
|
||||||
&options_adv_type,
|
|
||||||
&label_marked_data,
|
&label_marked_data,
|
||||||
&marked_data_sequence,
|
&marked_data_sequence,
|
||||||
&label_packet_index,
|
&label_packet_index,
|
||||||
@@ -371,13 +399,8 @@ BLETxView::BLETxView(NavigationView& nav)
|
|||||||
timer_count = 0;
|
timer_count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
options_adv_type.on_change = [this](size_t, int32_t i) {
|
|
||||||
pduType = (PKT_TYPE)i;
|
|
||||||
};
|
|
||||||
|
|
||||||
options_speed.set_selected_index(0);
|
options_speed.set_selected_index(0);
|
||||||
options_channel.set_selected_index(0);
|
options_channel.set_selected_index(3);
|
||||||
options_adv_type.set_selected_index(0);
|
|
||||||
|
|
||||||
check_rand_mac.set_value(false);
|
check_rand_mac.set_value(false);
|
||||||
check_rand_mac.on_select = [this](Checkbox&, bool v) {
|
check_rand_mac.on_select = [this](Checkbox&, bool v) {
|
||||||
@@ -482,17 +505,25 @@ void BLETxView::on_file_changed(const fs::path& new_file_path) {
|
|||||||
do {
|
do {
|
||||||
readUntil(data_file, packets[num_packets].macAddress, mac_address_size_str, ' ');
|
readUntil(data_file, packets[num_packets].macAddress, mac_address_size_str, ' ');
|
||||||
readUntil(data_file, packets[num_packets].advertisementData, max_packet_size_str, ' ');
|
readUntil(data_file, packets[num_packets].advertisementData, max_packet_size_str, ' ');
|
||||||
|
readUntil(data_file, packets[num_packets].packetType, max_packet_type_str, ' ');
|
||||||
readUntil(data_file, packets[num_packets].packetCount, max_packet_repeat_str, '\n');
|
readUntil(data_file, packets[num_packets].packetCount, max_packet_repeat_str, '\n');
|
||||||
|
|
||||||
uint64_t macAddressSize = strlen(packets[num_packets].macAddress);
|
uint64_t macAddressSize = strlen(packets[num_packets].macAddress);
|
||||||
uint64_t advertisementDataSize = strlen(packets[num_packets].advertisementData);
|
uint64_t advertisementDataSize = strlen(packets[num_packets].advertisementData);
|
||||||
uint64_t packetCountSize = strlen(packets[num_packets].packetCount);
|
uint64_t packetCountSize = strlen(packets[num_packets].packetCount);
|
||||||
|
uint64_t packetTypeSize = strlen(packets[num_packets].packetType);
|
||||||
|
|
||||||
packets[num_packets].packet_count = stringToUint32(packets[num_packets].packetCount);
|
packets[num_packets].packet_count = stringToUint32(packets[num_packets].packetCount);
|
||||||
|
packets[num_packets].pduType = (PKT_TYPE)get_pkt_type_from_string(packets[num_packets].packetType);
|
||||||
|
|
||||||
// Verify Data.
|
// Verify Data.
|
||||||
if ((macAddressSize == mac_address_size_str) && (advertisementDataSize < max_packet_size_str) && (packetCountSize < max_packet_repeat_str) &&
|
if ((macAddressSize == mac_address_size_str) &&
|
||||||
hasValidHexPairs(packets[num_packets].macAddress, macAddressSize / 2) && hasValidHexPairs(packets[num_packets].advertisementData, advertisementDataSize / 2) && (packets[num_packets].packet_count >= 1) && (packets[num_packets].packet_count < max_packet_repeat_count)) {
|
(advertisementDataSize < max_packet_size_str) &&
|
||||||
|
(packetCountSize < max_packet_repeat_str) &&
|
||||||
|
hasValidHexPairs(packets[num_packets].macAddress, macAddressSize / 2) &&
|
||||||
|
hasValidHexPairs(packets[num_packets].advertisementData, advertisementDataSize / 2) &&
|
||||||
|
(packets[num_packets].packet_count >= 1) && (packets[num_packets].packet_count < max_packet_repeat_count) &&
|
||||||
|
(packetTypeSize <= max_packet_type_str)) {
|
||||||
text_filename.set(truncate(file_path.filename().string(), 12));
|
text_filename.set(truncate(file_path.filename().string(), 12));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -510,6 +541,8 @@ void BLETxView::on_file_changed(const fs::path& new_file_path) {
|
|||||||
} while (num_packets < max_num_packets);
|
} while (num_packets < max_num_packets);
|
||||||
|
|
||||||
update_current_packet(packets[0], 0);
|
update_current_packet(packets[0], 0);
|
||||||
|
|
||||||
|
data_file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,6 +573,8 @@ void BLETxView::update_current_packet(BLETxPacket packet, uint32_t currentIndex)
|
|||||||
|
|
||||||
text_mac_address.set(formattedMacAddress);
|
text_mac_address.set(formattedMacAddress);
|
||||||
|
|
||||||
|
progressbar.set_max(packet.packet_count);
|
||||||
|
|
||||||
packet_counter = packet.packet_count;
|
packet_counter = packet.packet_count;
|
||||||
current_packet = currentIndex;
|
current_packet = currentIndex;
|
||||||
|
|
||||||
@@ -550,7 +585,7 @@ void BLETxView::update_current_packet(BLETxPacket packet, uint32_t currentIndex)
|
|||||||
dataFile.write("\n", 1);
|
dataFile.write("\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dataFile.~File();
|
dataFile.close();
|
||||||
|
|
||||||
auto result = FileWrapper::open(dataTempFilePath);
|
auto result = FileWrapper::open(dataTempFilePath);
|
||||||
|
|
||||||
|
@@ -38,6 +38,8 @@
|
|||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "file_path.hpp"
|
#include "file_path.hpp"
|
||||||
|
|
||||||
|
#include "ble_tx_app.hpp"
|
||||||
|
|
||||||
#include "recent_entries.hpp"
|
#include "recent_entries.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -91,8 +93,9 @@ struct BLETxPacket {
|
|||||||
char macAddress[13];
|
char macAddress[13];
|
||||||
char advertisementData[63];
|
char advertisementData[63];
|
||||||
char packetCount[11];
|
char packetCount[11];
|
||||||
|
char packetType[17];
|
||||||
uint32_t packet_count;
|
uint32_t packet_count;
|
||||||
PKT_TYPE packetType;
|
PKT_TYPE pduType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BLETxView : public View {
|
class BLETxView : public View {
|
||||||
@@ -109,8 +112,8 @@ class BLETxView : public View {
|
|||||||
bool is_active() const;
|
bool is_active() const;
|
||||||
void toggle();
|
void toggle();
|
||||||
void start();
|
void start();
|
||||||
|
void send_packet();
|
||||||
void stop();
|
void stop();
|
||||||
void reset();
|
|
||||||
void handle_replay_thread_done(const uint32_t return_code);
|
void handle_replay_thread_done(const uint32_t return_code);
|
||||||
void file_error();
|
void file_error();
|
||||||
bool saveFile(const std::filesystem::path& path);
|
bool saveFile(const std::filesystem::path& path);
|
||||||
@@ -122,7 +125,7 @@ class BLETxView : public View {
|
|||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
void on_file_changed(const std::filesystem::path& new_file_path);
|
void on_file_changed(const std::filesystem::path& new_file_path);
|
||||||
void on_save_file(const std::string value);
|
void on_save_file(const std::string value);
|
||||||
void on_tx_progress(const bool done);
|
void on_tx_progress(const bool done, uint32_t progress);
|
||||||
void on_random_data_change(std::string value);
|
void on_random_data_change(std::string value);
|
||||||
void update_current_packet(BLETxPacket packet, uint32_t currentIndex);
|
void update_current_packet(BLETxPacket packet, uint32_t currentIndex);
|
||||||
|
|
||||||
@@ -156,6 +159,8 @@ class BLETxView : public View {
|
|||||||
uint32_t packet_counter{0};
|
uint32_t packet_counter{0};
|
||||||
uint32_t num_packets{0};
|
uint32_t num_packets{0};
|
||||||
uint32_t current_packet{0};
|
uint32_t current_packet{0};
|
||||||
|
uint8_t packetTxCount{0};
|
||||||
|
bool packetDone = false;
|
||||||
bool random_mac = false;
|
bool random_mac = false;
|
||||||
bool file_override = false;
|
bool file_override = false;
|
||||||
|
|
||||||
@@ -170,17 +175,17 @@ class BLETxView : public View {
|
|||||||
std::vector<uint16_t> markedBytes{};
|
std::vector<uint16_t> markedBytes{};
|
||||||
CursorPos cursor_pos{};
|
CursorPos cursor_pos{};
|
||||||
uint8_t marked_counter = 0;
|
uint8_t marked_counter = 0;
|
||||||
|
uint8_t advCount = 0;
|
||||||
|
|
||||||
static constexpr uint8_t mac_address_size_str{12};
|
static constexpr uint8_t mac_address_size_str{12};
|
||||||
static constexpr uint8_t max_packet_size_str{62};
|
static constexpr uint8_t max_packet_size_str{62};
|
||||||
static constexpr uint8_t max_packet_repeat_str{10};
|
static constexpr uint8_t max_packet_repeat_str{10};
|
||||||
|
static constexpr uint8_t max_packet_type_str{16};
|
||||||
static constexpr uint32_t max_packet_repeat_count{UINT32_MAX};
|
static constexpr uint32_t max_packet_repeat_count{UINT32_MAX};
|
||||||
static constexpr uint32_t max_num_packets{32};
|
static constexpr uint32_t max_num_packets{32};
|
||||||
|
|
||||||
BLETxPacket packets[max_num_packets];
|
BLETxPacket packets[max_num_packets];
|
||||||
|
|
||||||
PKT_TYPE pduType = {PKT_TYPE_DISCOVERY};
|
|
||||||
|
|
||||||
static constexpr auto header_height = 10 * 16;
|
static constexpr auto header_height = 10 * 16;
|
||||||
static constexpr auto switch_button_height = 6 * 16;
|
static constexpr auto switch_button_height = 6 * 16;
|
||||||
|
|
||||||
@@ -216,7 +221,7 @@ class BLETxView : public View {
|
|||||||
true};
|
true};
|
||||||
|
|
||||||
ImageButton button_play{
|
ImageButton button_play{
|
||||||
{screen_width - 2 * 8, 2 * 16, 2 * 8, 1 * 16},
|
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
||||||
&bitmap_play,
|
&bitmap_play,
|
||||||
Theme::getInstance()->fg_green->foreground,
|
Theme::getInstance()->fg_green->foreground,
|
||||||
Theme::getInstance()->fg_green->background};
|
Theme::getInstance()->fg_green->background};
|
||||||
@@ -227,11 +232,11 @@ class BLETxView : public View {
|
|||||||
OptionsField options_speed{
|
OptionsField options_speed{
|
||||||
{7 * 8, 6 * 8},
|
{7 * 8, 6 * 8},
|
||||||
3,
|
3,
|
||||||
{{"1 ", 1}, // 16ms
|
{{"1 ", 2}, // 25ms
|
||||||
{"2 ", 2}, // 32ms
|
{"2 ", 4}, // 50ms
|
||||||
{"3 ", 3}, // 48ms
|
{"3 ", 6}, // 75ms
|
||||||
{"4 ", 6}, // 100ms
|
{"4 ", 8}, // 100ms
|
||||||
{"5 ", 12}}}; // 200ms
|
{"5 ", 12}}}; // 150ms
|
||||||
|
|
||||||
OptionsField options_channel{
|
OptionsField options_channel{
|
||||||
{11 * 8, 6 * 8},
|
{11 * 8, 6 * 8},
|
||||||
@@ -288,7 +293,7 @@ class BLETxView : public View {
|
|||||||
{{0 * 8, 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}};
|
{{0 * 8, 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
TextViewer dataEditView{
|
TextViewer dataEditView{
|
||||||
{0, 9 * 18, screen_width, screen_height - 80}};
|
{0, 9 * 18, 240, 240}};
|
||||||
|
|
||||||
Button button_clear_marked{
|
Button button_clear_marked{
|
||||||
{1 * 8, 14 * 16, 13 * 8, 3 * 8},
|
{1 * 8, 14 * 16, 13 * 8, 3 * 8},
|
||||||
@@ -320,7 +325,7 @@ class BLETxView : public View {
|
|||||||
Message::ID::TXProgress,
|
Message::ID::TXProgress,
|
||||||
[this](const Message* const p) {
|
[this](const Message* const p) {
|
||||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||||
this->on_tx_progress(message.done);
|
this->on_tx_progress(message.done, message.progress);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_frame_sync{
|
MessageHandlerRegistration message_handler_frame_sync{
|
||||||
|
@@ -96,22 +96,7 @@ void ERTRecentEntry::update(const ert::Packet& packet) {
|
|||||||
packet_type = packet.type();
|
packet_type = packet.type();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ui {
|
namespace ui::external_app::ert_app {
|
||||||
|
|
||||||
template <>
|
|
||||||
void RecentEntriesTable<ERTRecentEntries>::draw(
|
|
||||||
const Entry& entry,
|
|
||||||
const Rect& target_rect,
|
|
||||||
Painter& painter,
|
|
||||||
const Style& style) {
|
|
||||||
std::string line = ert::format::id(entry.id) + " " + ert::format::commodity_type(entry.commodity_type) + " " + ert::format::consumption(entry.last_consumption) + " ";
|
|
||||||
|
|
||||||
line += (entry.packet_type == ert::Packet::Type::SCM) ? ert::format::tamper_flags_scm(entry.last_tamper_flags) : ert::format::tamper_flags(entry.last_tamper_flags);
|
|
||||||
line += (entry.received_count > 99) ? " ++" : to_string_dec_uint(entry.received_count, 3);
|
|
||||||
|
|
||||||
line.resize(target_rect.width() / 8, ' ');
|
|
||||||
painter.draw_string(target_rect.location(), style, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERTAppView::ERTAppView(NavigationView& nav)
|
ERTAppView::ERTAppView(NavigationView& nav)
|
||||||
: nav_{nav} {
|
: nav_{nav} {
|
||||||
@@ -182,4 +167,21 @@ void ERTAppView::on_freqchg(int64_t freq) {
|
|||||||
field_frequency.set_value(freq);
|
field_frequency.set_value(freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui::external_app::ert_app */
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
template <>
|
||||||
|
void RecentEntriesTable<ui::external_app::ert_app::ERTRecentEntries>::draw(
|
||||||
|
const Entry& entry,
|
||||||
|
const Rect& target_rect,
|
||||||
|
Painter& painter,
|
||||||
|
const Style& style) {
|
||||||
|
std::string line = ert::format::id(entry.id) + " " + ert::format::commodity_type(entry.commodity_type) + " " + ert::format::consumption(entry.last_consumption) + " ";
|
||||||
|
|
||||||
|
line += (entry.packet_type == ert::Packet::Type::SCM) ? ert::format::tamper_flags_scm(entry.last_tamper_flags) : ert::format::tamper_flags(entry.last_tamper_flags);
|
||||||
|
line += (entry.received_count > 99) ? " ++" : to_string_dec_uint(entry.received_count, 3);
|
||||||
|
|
||||||
|
line.resize(target_rect.width() / 8, ' ');
|
||||||
|
painter.draw_string(target_rect.location(), style, line);
|
||||||
|
}
|
||||||
|
} // namespace ui
|
@@ -104,10 +104,9 @@ class ERTLogger {
|
|||||||
LogFile log_file{};
|
LogFile log_file{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ui::external_app::ert_app {
|
||||||
|
|
||||||
using ERTRecentEntries = RecentEntries<ERTRecentEntry>;
|
using ERTRecentEntries = RecentEntries<ERTRecentEntry>;
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
|
|
||||||
using ERTRecentEntriesView = RecentEntriesView<ERTRecentEntries>;
|
using ERTRecentEntriesView = RecentEntriesView<ERTRecentEntries>;
|
||||||
|
|
||||||
class ERTAppView : public View {
|
class ERTAppView : public View {
|
||||||
@@ -188,6 +187,6 @@ class ERTAppView : public View {
|
|||||||
void on_show_list();
|
void on_show_list();
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui::external_app::ert_app */
|
||||||
|
|
||||||
#endif /*__ERT_APP_H__*/
|
#endif /*__ERT_APP_H__*/
|
83
firmware/application/external/ert/main.cpp
vendored
Normal file
83
firmware/application/external/ert/main.cpp
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Bernd Herzog
|
||||||
|
*
|
||||||
|
* This file is part of PortaPack.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "ert_app.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "external_app.hpp"
|
||||||
|
|
||||||
|
namespace ui::external_app::ert_app {
|
||||||
|
void initialize_app(ui::NavigationView& nav) {
|
||||||
|
nav.push<ERTAppView>();
|
||||||
|
}
|
||||||
|
} // namespace ui::external_app::ert_app
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
__attribute__((section(".external_app.app_ert.application_information"), used)) application_information_t _application_information_ert = {
|
||||||
|
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||||
|
/*.externalAppEntry = */ ui::external_app::ert_app::initialize_app,
|
||||||
|
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||||
|
/*.app_version = */ VERSION_MD5,
|
||||||
|
|
||||||
|
/*.app_name = */ "ERT Meter",
|
||||||
|
/*.bitmap_data = */ {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x0F,
|
||||||
|
0x80,
|
||||||
|
0x7F,
|
||||||
|
0xC0,
|
||||||
|
0x0F,
|
||||||
|
0xFC,
|
||||||
|
0x0F,
|
||||||
|
0xC2,
|
||||||
|
0x0F,
|
||||||
|
0x82,
|
||||||
|
0x7F,
|
||||||
|
0x01,
|
||||||
|
0x0F,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x21,
|
||||||
|
0x05,
|
||||||
|
0x53,
|
||||||
|
0x09,
|
||||||
|
0x56,
|
||||||
|
0x09,
|
||||||
|
0x50,
|
||||||
|
0x05,
|
||||||
|
0x50,
|
||||||
|
0x05,
|
||||||
|
0x20,
|
||||||
|
0xAD,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
},
|
||||||
|
/*.icon_color = */ ui::Color::green().v,
|
||||||
|
/*.menu_location = */ app_location_t::RX,
|
||||||
|
/*.desired_menu_position = */ -1,
|
||||||
|
|
||||||
|
/*.m4_app_tag = portapack::spi_flash::image_tag_none */ {'P', 'E', 'R', 'T'},
|
||||||
|
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||||
|
};
|
||||||
|
}
|
5
firmware/application/external/external.cmake
vendored
5
firmware/application/external/external.cmake
vendored
@@ -232,6 +232,10 @@ set(EXTCPPSRC
|
|||||||
#battleship
|
#battleship
|
||||||
external/battleship/main.cpp
|
external/battleship/main.cpp
|
||||||
external/battleship/ui_battleship.cpp
|
external/battleship/ui_battleship.cpp
|
||||||
|
|
||||||
|
#ert
|
||||||
|
external/ert/main.cpp
|
||||||
|
external/ert/ert_app.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EXTAPPLIST
|
set(EXTAPPLIST
|
||||||
@@ -291,4 +295,5 @@ set(EXTAPPLIST
|
|||||||
spaceinv
|
spaceinv
|
||||||
blackjack
|
blackjack
|
||||||
battleship
|
battleship
|
||||||
|
ert
|
||||||
)
|
)
|
||||||
|
6
firmware/application/external/external.ld
vendored
6
firmware/application/external/external.ld
vendored
@@ -79,6 +79,7 @@ MEMORY
|
|||||||
ram_external_app_spaceinv (rwx) : org = 0xADE60000, len = 32k
|
ram_external_app_spaceinv (rwx) : org = 0xADE60000, len = 32k
|
||||||
ram_external_app_blackjack (rwx) : org = 0xADE70000, len = 32k
|
ram_external_app_blackjack (rwx) : org = 0xADE70000, len = 32k
|
||||||
ram_external_app_battleship (rwx) : org = 0xADE80000, len = 32k
|
ram_external_app_battleship (rwx) : org = 0xADE80000, len = 32k
|
||||||
|
ram_external_app_ert (rwx) : org = 0xADE90000, len = 32k
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
@@ -419,5 +420,10 @@ SECTIONS
|
|||||||
*(*ui*external_app*battleship*);
|
*(*ui*external_app*battleship*);
|
||||||
} > ram_external_app_battleship
|
} > ram_external_app_battleship
|
||||||
|
|
||||||
|
.external_app_ert : ALIGN(4) SUBALIGN(4)
|
||||||
|
{
|
||||||
|
KEEP(*(.external_app.app_ert.application_information));
|
||||||
|
*(*ui*external_app*ert*);
|
||||||
|
} > ram_external_app_ert
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -70,7 +70,6 @@
|
|||||||
#include "ble_rx_app.hpp"
|
#include "ble_rx_app.hpp"
|
||||||
#include "ble_tx_app.hpp"
|
#include "ble_tx_app.hpp"
|
||||||
#include "capture_app.hpp"
|
#include "capture_app.hpp"
|
||||||
#include "ert_app.hpp"
|
|
||||||
#include "pocsag_app.hpp"
|
#include "pocsag_app.hpp"
|
||||||
#include "soundboard_app.hpp"
|
#include "soundboard_app.hpp"
|
||||||
|
|
||||||
@@ -131,7 +130,6 @@ const NavigationView::AppList NavigationView::appList = {
|
|||||||
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
|
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
|
||||||
{"audio", "Audio", RX, Color::green(), &bitmap_icon_speaker, new ViewFactory<AnalogAudioView>()},
|
{"audio", "Audio", RX, Color::green(), &bitmap_icon_speaker, new ViewFactory<AnalogAudioView>()},
|
||||||
{"blerx", "BLE Rx", RX, Color::green(), &bitmap_icon_btle, new ViewFactory<BLERxView>()},
|
{"blerx", "BLE Rx", RX, Color::green(), &bitmap_icon_btle, new ViewFactory<BLERxView>()},
|
||||||
{"ert", "ERT Meter", RX, Color::green(), &bitmap_icon_ert, new ViewFactory<ERTAppView>()},
|
|
||||||
{"pocsag", "POCSAG", RX, Color::green(), &bitmap_icon_pocsag, new ViewFactory<POCSAGAppView>()},
|
{"pocsag", "POCSAG", RX, Color::green(), &bitmap_icon_pocsag, new ViewFactory<POCSAGAppView>()},
|
||||||
{"radiosonde", "Radiosnde", RX, Color::green(), &bitmap_icon_sonde, new ViewFactory<SondeView>()},
|
{"radiosonde", "Radiosnde", RX, Color::green(), &bitmap_icon_sonde, new ViewFactory<SondeView>()},
|
||||||
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
|
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
|
||||||
|
@@ -30,10 +30,10 @@
|
|||||||
|
|
||||||
#define new_way
|
#define new_way
|
||||||
|
|
||||||
int BTLETxProcessor::gen_sample_from_phy_bit(char* bit, char* sample, int num_bit) {
|
int BTLETxProcessor::gen_sample_from_phy_bit(char* bit, int8_t* sample, int num_bit) {
|
||||||
int num_sample = (num_bit * SAMPLE_PER_SYMBOL) + (LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL);
|
int num_sample = (num_bit * SAMPLE_PER_SYMBOL) + (LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL);
|
||||||
|
|
||||||
int8_t* tmp_phy_bit_over_sampling_int8 = (int8_t*)tmp_phy_bit_over_sampling;
|
memset(tmp_phy_bit_over_sampling_int8, 0, sizeof(tmp_phy_bit_over_sampling_int8));
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@@ -242,6 +242,7 @@ void BTLETxProcessor::fill_adv_pdu_header(PKT_INFO* pkt, int txadd, int rxadd, i
|
|||||||
bit_out[2] = 1;
|
bit_out[2] = 1;
|
||||||
bit_out[1] = 0;
|
bit_out[1] = 0;
|
||||||
bit_out[0] = 0;
|
bit_out[0] = 0;
|
||||||
|
rxadd = 1; // Scan response assumed to be with random address.
|
||||||
} else if (pkt->pkt_type == CONNECT_REQ) {
|
} else if (pkt->pkt_type == CONNECT_REQ) {
|
||||||
bit_out[3] = 0;
|
bit_out[3] = 0;
|
||||||
bit_out[2] = 1;
|
bit_out[2] = 1;
|
||||||
@@ -279,14 +280,12 @@ void BTLETxProcessor::fill_adv_pdu_header(PKT_INFO* pkt, int txadd, int rxadd, i
|
|||||||
int BTLETxProcessor::calculate_sample_for_ADV(PKT_INFO* pkt) {
|
int BTLETxProcessor::calculate_sample_for_ADV(PKT_INFO* pkt) {
|
||||||
pkt->num_info_bit = 0;
|
pkt->num_info_bit = 0;
|
||||||
|
|
||||||
// gen preamble and access address
|
pkt->num_info_bit = pkt->num_info_bit + convert_hex_to_bit(AA, pkt->info_bit, 0, 1);
|
||||||
const char* AA = "AA";
|
pkt->num_info_bit = pkt->num_info_bit + convert_hex_to_bit(AAValue, pkt->info_bit + pkt->num_info_bit, 0, 4);
|
||||||
const char* AAValue = "D6BE898E";
|
|
||||||
pkt->num_info_bit = pkt->num_info_bit + convert_hex_to_bit((char*)AA, pkt->info_bit, 0, 1);
|
|
||||||
pkt->num_info_bit = pkt->num_info_bit + convert_hex_to_bit((char*)AAValue, pkt->info_bit + pkt->num_info_bit, 0, 4);
|
|
||||||
|
|
||||||
// get txadd and rxadd
|
// get txadd and rxadd
|
||||||
int txadd = 0, rxadd = 0;
|
// Tx assumed to be random address.
|
||||||
|
int txadd = 1, rxadd = 0;
|
||||||
|
|
||||||
pkt->num_info_bit = pkt->num_info_bit + 16; // 16 is header length
|
pkt->num_info_bit = pkt->num_info_bit + 16; // 16 is header length
|
||||||
|
|
||||||
@@ -332,39 +331,56 @@ int BTLETxProcessor::calculate_pkt_info(PKT_INFO* pkt) {
|
|||||||
void BTLETxProcessor::execute(const buffer_c8_t& buffer) {
|
void BTLETxProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
int8_t re, im;
|
int8_t re, im;
|
||||||
|
|
||||||
// This is called at 4M/2048 = 1953Hz
|
if (!configured) {
|
||||||
for (size_t i = 0; i < buffer.count; i++) {
|
for (size_t i = 0; i < buffer.count; i++) {
|
||||||
if (configured) {
|
buffer.p[i] = {0, 0}; // Fill the buffer with zeros if not configured
|
||||||
// This is going to loop through each sample bit and push it to the output buffer.
|
}
|
||||||
if (sample_count > length) {
|
return;
|
||||||
configured = false;
|
}
|
||||||
sample_count = 0;
|
|
||||||
|
|
||||||
|
if (configured) {
|
||||||
|
switch (txprogress_message.progress) {
|
||||||
|
case 1:
|
||||||
|
case 2: {
|
||||||
|
for (size_t i = 0; i < buffer.count; i++) {
|
||||||
|
buffer.p[i] = {0, 0}; // Pre and Post pad BLE Packet.
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0: {
|
||||||
|
size_t i = 0;
|
||||||
|
for (i = 0; (i < buffer.count) && (sample_count < length); i++) {
|
||||||
|
re = packets.phy_sample[sample_count++];
|
||||||
|
im = packets.phy_sample[sample_count++];
|
||||||
|
|
||||||
|
buffer.p[i] = {re, im};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample_count >= length && i < buffer.count) {
|
||||||
|
// Fill the rest of the buffer with zeros if we reach the end of the packet
|
||||||
|
for (; i < buffer.count; i++) {
|
||||||
|
buffer.p[i] = {0, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 3: {
|
||||||
|
for (size_t i = 0; i < buffer.count; i++) {
|
||||||
|
buffer.p[i] = {0, 0}; // Pre and Post pad BLE Packet.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample_count >= length) {
|
||||||
|
sample_count = 0;
|
||||||
|
configured = false;
|
||||||
|
|
||||||
|
doneSending = true;
|
||||||
txprogress_message.done = true;
|
txprogress_message.done = true;
|
||||||
shared_memory.application_queue.push(txprogress_message);
|
shared_memory.application_queue.push(txprogress_message);
|
||||||
} else {
|
}
|
||||||
// Real and imaginary was already calculated in gen_sample_from_phy_bit.
|
} break;
|
||||||
// It was processed from each data bit, run through a Gaussian Filter, and then ran through sin and cos table to get each IQ bit.
|
}
|
||||||
re = (int8_t)packets.phy_sample[sample_count++];
|
|
||||||
im = (int8_t)packets.phy_sample[sample_count++];
|
|
||||||
|
|
||||||
buffer.p[i] = {re, im};
|
|
||||||
|
|
||||||
if (progress_count >= progress_notice) {
|
|
||||||
progress_count = 0;
|
|
||||||
txprogress_message.progress++;
|
txprogress_message.progress++;
|
||||||
txprogress_message.done = false;
|
|
||||||
shared_memory.application_queue.push(txprogress_message);
|
|
||||||
} else {
|
|
||||||
progress_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
re = 0;
|
|
||||||
im = 0;
|
|
||||||
|
|
||||||
buffer.p[i] = {re, im};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,11 +413,13 @@ void BTLETxProcessor::configure(const BTLETxConfigureMessage& message) {
|
|||||||
// Starting at sample_count 0 since packets.num_phy_sample contains every sample needed to be sent out.
|
// Starting at sample_count 0 since packets.num_phy_sample contains every sample needed to be sent out.
|
||||||
sample_count = 0;
|
sample_count = 0;
|
||||||
progress_count = 0;
|
progress_count = 0;
|
||||||
|
repeatCount = 0;
|
||||||
progress_notice = 64;
|
progress_notice = 64;
|
||||||
|
|
||||||
txprogress_message.progress = 0;
|
txprogress_message.progress = 0;
|
||||||
txprogress_message.done = false;
|
txprogress_message.done = false;
|
||||||
configured = true;
|
configured = true;
|
||||||
|
doneSending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
@@ -80,18 +80,11 @@ class BTLETxProcessor : public BasebandProcessor {
|
|||||||
int num_info_bit;
|
int num_info_bit;
|
||||||
char info_bit[MAX_NUM_PHY_BYTE * 8]; // without CRC and whitening
|
char info_bit[MAX_NUM_PHY_BYTE * 8]; // without CRC and whitening
|
||||||
|
|
||||||
int num_info_byte;
|
|
||||||
uint8_t info_byte[MAX_NUM_PHY_BYTE];
|
|
||||||
|
|
||||||
int num_phy_bit;
|
int num_phy_bit;
|
||||||
char phy_bit[MAX_NUM_PHY_BYTE * 8]; // all bits which will be fed to GFSK modulator
|
char phy_bit[MAX_NUM_PHY_BYTE * 8]; // all bits which will be fed to GFSK modulator
|
||||||
|
|
||||||
int num_phy_byte;
|
|
||||||
uint8_t phy_byte[MAX_NUM_PHY_BYTE];
|
|
||||||
|
|
||||||
int num_phy_sample;
|
int num_phy_sample;
|
||||||
char phy_sample[2 * MAX_NUM_PHY_SAMPLE]; // GFSK output to D/A (hackrf board)
|
int8_t phy_sample[2 * MAX_NUM_PHY_SAMPLE]; // GFSK output to D/A (hackrf board)
|
||||||
int8_t phy_sample1[2 * MAX_NUM_PHY_SAMPLE]; // GFSK output to D/A (hackrf board)
|
|
||||||
|
|
||||||
int space; // how many millisecond null signal shouwl be padded after this packet
|
int space; // how many millisecond null signal shouwl be padded after this packet
|
||||||
};
|
};
|
||||||
@@ -108,22 +101,27 @@ class BTLETxProcessor : public BasebandProcessor {
|
|||||||
void crc24(char* bit_in, int num_bit, char* init_hex, char* crc_result);
|
void crc24(char* bit_in, int num_bit, char* init_hex, char* crc_result);
|
||||||
int convert_hex_to_bit(char* hex, char* bit, int stream_flip, int octet_limit);
|
int convert_hex_to_bit(char* hex, char* bit, int stream_flip, int octet_limit);
|
||||||
void octet_hex_to_bit(char* hex, char* bit);
|
void octet_hex_to_bit(char* hex, char* bit);
|
||||||
int gen_sample_from_phy_bit(char* bit, char* sample, int num_bit);
|
int gen_sample_from_phy_bit(char* bit, int8_t* sample, int num_bit);
|
||||||
bool configured = false;
|
bool configured = false;
|
||||||
|
|
||||||
float tmp_phy_bit_over_sampling[MAX_NUM_PHY_SAMPLE + 2 * LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL];
|
int8_t tmp_phy_bit_over_sampling_int8[MAX_NUM_PHY_SAMPLE + 2 * LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL];
|
||||||
float gauss_coef[LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL] = {7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06};
|
float gauss_coef[LEN_GAUSS_FILTER * SAMPLE_PER_SYMBOL] = {7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06};
|
||||||
|
|
||||||
uint32_t samples_per_bit{4};
|
uint32_t samples_per_bit{4};
|
||||||
uint32_t channel_number{37};
|
uint32_t channel_number{37};
|
||||||
char macAddress[13] = "FFFFFFFFFF";
|
char macAddress[13] = "FFFFFFFFFF";
|
||||||
|
char AA[3] = "AA";
|
||||||
|
char AAValue[9] = "D6BE898E";
|
||||||
char advertisementData[63] = {0};
|
char advertisementData[63] = {0};
|
||||||
|
|
||||||
uint32_t length{0};
|
uint32_t length{0};
|
||||||
uint32_t shift_zero{}, shift_one{};
|
uint32_t shift_zero{}, shift_one{};
|
||||||
uint32_t progress_notice{}, progress_count{0};
|
uint32_t progress_notice{}, progress_count{0};
|
||||||
uint32_t sample_count{0};
|
uint32_t sample_count{0};
|
||||||
|
uint32_t paddingCount{0};
|
||||||
|
uint32_t repeatCount{0};
|
||||||
uint32_t phase{0}, sphase{0};
|
uint32_t phase{0}, sphase{0};
|
||||||
|
bool doneSending{false};
|
||||||
|
|
||||||
uint8_t cur_bit{0};
|
uint8_t cur_bit{0};
|
||||||
uint16_t bit_pos{0};
|
uint16_t bit_pos{0};
|
||||||
|
@@ -1,464 +1,464 @@
|
|||||||
010203040506 03032CFE06162CFE000006020AA8 1
|
010203040506 03032CFE06162CFE000006020AA8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000007020AA9 1
|
010203040506 03032CFE06162CFE000007020AA9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000008020AAA 1
|
010203040506 03032CFE06162CFE000008020AAA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000009020AAB 1
|
010203040506 03032CFE06162CFE000009020AAB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00000A020AAC 1
|
010203040506 03032CFE06162CFE00000A020AAC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00000B020AAD 1
|
010203040506 03032CFE06162CFE00000B020AAD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00000C020AAE 1
|
010203040506 03032CFE06162CFE00000C020AAE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00000D020AAF 1
|
010203040506 03032CFE06162CFE00000D020AAF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000035020AB0 1
|
010203040506 03032CFE06162CFE000035020AB0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000047020AB1 1
|
010203040506 03032CFE06162CFE000047020AB1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000048020AB2 1
|
010203040506 03032CFE06162CFE000048020AB2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE000049020AB3 1
|
010203040506 03032CFE06162CFE000049020AB3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0000F0020AB4 1
|
010203040506 03032CFE06162CFE0000F0020AB4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0002F0020AB5 1
|
010203040506 03032CFE06162CFE0002F0020AB5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0003F0020AB6 1
|
010203040506 03032CFE06162CFE0003F0020AB6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE001000020AB7 1
|
010203040506 03032CFE06162CFE001000020AB7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE002000020AB8 1
|
010203040506 03032CFE06162CFE002000020AB8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE003000020AB9 1
|
010203040506 03032CFE06162CFE003000020AB9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE003001020ABA 1
|
010203040506 03032CFE06162CFE003001020ABA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE003B41020ABB 1
|
010203040506 03032CFE06162CFE003B41020ABB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE003D8A020ABC 1
|
010203040506 03032CFE06162CFE003D8A020ABC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0052DA020ABD 1
|
010203040506 03032CFE06162CFE0052DA020ABD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE005BC3020ABE 1
|
010203040506 03032CFE06162CFE005BC3020ABE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE008F7D020ABF 1
|
010203040506 03032CFE06162CFE008F7D020ABF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00A168020AC0 1
|
010203040506 03032CFE06162CFE00A168020AC0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00AA48020AC1 1
|
010203040506 03032CFE06162CFE00AA48020AC1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00AA91020AC2 1
|
010203040506 03032CFE06162CFE00AA91020AC2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00B727020AC3 1
|
010203040506 03032CFE06162CFE00B727020AC3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00C95C020AC4 1
|
010203040506 03032CFE06162CFE00C95C020AC4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00F7D4020AC5 1
|
010203040506 03032CFE06162CFE00F7D4020AC5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE00FA72020AC6 1
|
010203040506 03032CFE06162CFE00FA72020AC6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0100F0020AC7 1
|
010203040506 03032CFE06162CFE0100F0020AC7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0102F0020AC8 1
|
010203040506 03032CFE06162CFE0102F0020AC8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0103F0020AC9 1
|
010203040506 03032CFE06162CFE0103F0020AC9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE011242020ACA 1
|
010203040506 03032CFE06162CFE011242020ACA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE013D8A020ACB 1
|
010203040506 03032CFE06162CFE013D8A020ACB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE01AA91020ACC 1
|
010203040506 03032CFE06162CFE01AA91020ACC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE01C95C020ACD 1
|
010203040506 03032CFE06162CFE01C95C020ACD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE01E5CE020ACE 1
|
010203040506 03032CFE06162CFE01E5CE020ACE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE01EEB4020ACF 1
|
010203040506 03032CFE06162CFE01EEB4020ACF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0200F0020AD0 1
|
010203040506 03032CFE06162CFE0200F0020AD0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0202F0020AD1 1
|
010203040506 03032CFE06162CFE0202F0020AD1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0203F0020AD2 1
|
010203040506 03032CFE06162CFE0203F0020AD2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02AA91020AD3 1
|
010203040506 03032CFE06162CFE02AA91020AD3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02C95C020AD4 1
|
010203040506 03032CFE06162CFE02C95C020AD4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02D815020AD5 1
|
010203040506 03032CFE06162CFE02D815020AD5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02D886020AD6 1
|
010203040506 03032CFE06162CFE02D886020AD6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02DD4F020AD7 1
|
010203040506 03032CFE06162CFE02DD4F020AD7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02E2A9020AD8 1
|
010203040506 03032CFE06162CFE02E2A9020AD8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE02F637020AD9 1
|
010203040506 03032CFE06162CFE02F637020AD9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0302F0020ADA 1
|
010203040506 03032CFE06162CFE0302F0020ADA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0303F0020ADB 1
|
010203040506 03032CFE06162CFE0303F0020ADB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE035754020ADC 1
|
010203040506 03032CFE06162CFE035754020ADC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE035764020ADD 1
|
010203040506 03032CFE06162CFE035764020ADD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE038B91020ADE 1
|
010203040506 03032CFE06162CFE038B91020ADE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE038CC7020ADF 1
|
010203040506 03032CFE06162CFE038CC7020ADF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE038F16020AE0 1
|
010203040506 03032CFE06162CFE038F16020AE0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE039F8F020AE1 1
|
010203040506 03032CFE06162CFE039F8F020AE1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE03AA91020AE2 1
|
010203040506 03032CFE06162CFE03AA91020AE2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE03B716020AE3 1
|
010203040506 03032CFE06162CFE03B716020AE3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE03C95C020AE4 1
|
010203040506 03032CFE06162CFE03C95C020AE4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE03C99C020AE5 1
|
010203040506 03032CFE06162CFE03C99C020AE5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE03F5D4020AE6 1
|
010203040506 03032CFE06162CFE03F5D4020AE6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0402F0020AE7 1
|
010203040506 03032CFE06162CFE0402F0020AE7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0403F0020AE8 1
|
010203040506 03032CFE06162CFE0403F0020AE8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE045754020AE9 1
|
010203040506 03032CFE06162CFE045754020AE9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE045764020AEA 1
|
010203040506 03032CFE06162CFE045764020AEA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE04AA91020AEB 1
|
010203040506 03032CFE06162CFE04AA91020AEB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE04ACFC020AEC 1
|
010203040506 03032CFE06162CFE04ACFC020AEC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE04AFB8020AED 1
|
010203040506 03032CFE06162CFE04AFB8020AED DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE04C95C020AEE 1
|
010203040506 03032CFE06162CFE04C95C020AEE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0502F0020AEF 1
|
010203040506 03032CFE06162CFE0502F0020AEF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0503F0020AF0 1
|
010203040506 03032CFE06162CFE0503F0020AF0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE050F0C020AF1 1
|
010203040506 03032CFE06162CFE050F0C020AF1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE052CC7020AF2 1
|
010203040506 03032CFE06162CFE052CC7020AF2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE054B2D020AF3 1
|
010203040506 03032CFE06162CFE054B2D020AF3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0577B1020AF4 1
|
010203040506 03032CFE06162CFE0577B1020AF4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE057802020AF5 1
|
010203040506 03032CFE06162CFE057802020AF5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0582FD020AF6 1
|
010203040506 03032CFE06162CFE0582FD020AF6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE058D08020AF7 1
|
010203040506 03032CFE06162CFE058D08020AF7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE05A963020AF8 1
|
010203040506 03032CFE06162CFE05A963020AF8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE05A9BC020AF9 1
|
010203040506 03032CFE06162CFE05A9BC020AF9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE05AA91020AFA 1
|
010203040506 03032CFE06162CFE05AA91020AFA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE05C452020AFB 1
|
010203040506 03032CFE06162CFE05C452020AFB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE05C95C020AFC 1
|
010203040506 03032CFE06162CFE05C95C020AFC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE060000020AFD 1
|
010203040506 03032CFE06162CFE060000020AFD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0602F0020AFE 1
|
010203040506 03032CFE06162CFE0602F0020AFE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0603F0020AFF 1
|
010203040506 03032CFE06162CFE0603F0020AFF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0660D7020B00 1
|
010203040506 03032CFE06162CFE0660D7020B00 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE06AE20020B01 1
|
010203040506 03032CFE06162CFE06AE20020B01 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE06C197020B02 1
|
010203040506 03032CFE06162CFE06C197020B02 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE06C95C020B03 1
|
010203040506 03032CFE06162CFE06C95C020B03 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE06D8FC020B04 1
|
010203040506 03032CFE06162CFE06D8FC020B04 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE070000020B05 1
|
010203040506 03032CFE06162CFE070000020B05 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0702F0020B06 1
|
010203040506 03032CFE06162CFE0702F0020B06 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0703F0020B07 1
|
010203040506 03032CFE06162CFE0703F0020B07 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0X071C020B08 1
|
010203040506 03032CFE06162CFE0X071C020B08 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0744B6020B09 1
|
010203040506 03032CFE06162CFE0744B6020B09 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE07A41C020B0A 1
|
010203040506 03032CFE06162CFE07A41C020B0A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE07C95C020B0B 1
|
010203040506 03032CFE06162CFE07C95C020B0B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE07F426020B0C 1
|
010203040506 03032CFE06162CFE07F426020B0C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE080000020B0D 1
|
010203040506 03032CFE06162CFE080000020B0D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0802F0020B0E 1
|
010203040506 03032CFE06162CFE0802F0020B0E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0803F0020B0F 1
|
010203040506 03032CFE06162CFE0803F0020B0F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE090000020B10 1
|
010203040506 03032CFE06162CFE090000020B10 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0903F0020B11 1
|
010203040506 03032CFE06162CFE0903F0020B11 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0A0000020B12 1
|
010203040506 03032CFE06162CFE0A0000020B12 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0B0000020B13 1
|
010203040506 03032CFE06162CFE0B0000020B13 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0C0000020B14 1
|
010203040506 03032CFE06162CFE0C0000020B14 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0DC6BF020B15 1
|
010203040506 03032CFE06162CFE0DC6BF020B15 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0DC95C020B16 1
|
010203040506 03032CFE06162CFE0DC95C020B16 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0DEC2B020B17 1
|
010203040506 03032CFE06162CFE0DEC2B020B17 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0E138D020B18 1
|
010203040506 03032CFE06162CFE0E138D020B18 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0E30C3020B19 1
|
010203040506 03032CFE06162CFE0E30C3020B19 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0EC95C020B1A 1
|
010203040506 03032CFE06162CFE0EC95C020B1A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0ECE95020B1B 1
|
010203040506 03032CFE06162CFE0ECE95020B1B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0F0993020B1C 1
|
010203040506 03032CFE06162CFE0F0993020B1C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0F1B8D020B1D 1
|
010203040506 03032CFE06162CFE0F1B8D020B1D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0F232A020B1E 1
|
010203040506 03032CFE06162CFE0F232A020B1E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE0F2D16020B1F 1
|
010203040506 03032CFE06162CFE0F2D16020B1F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1E89A7020B20 1
|
010203040506 03032CFE06162CFE1E89A7020B20 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1E8B18020B21 1
|
010203040506 03032CFE06162CFE1E8B18020B21 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1E955B020B22 1
|
010203040506 03032CFE06162CFE1E955B020B22 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1EC95C020B23 1
|
010203040506 03032CFE06162CFE1EC95C020B23 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1ED9F9020B24 1
|
010203040506 03032CFE06162CFE1ED9F9020B24 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1EE890020B25 1
|
010203040506 03032CFE06162CFE1EE890020B25 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1EEDF5020B26 1
|
010203040506 03032CFE06162CFE1EEDF5020B26 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F1101020B27 1
|
010203040506 03032CFE06162CFE1F1101020B27 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F181A020B28 1
|
010203040506 03032CFE06162CFE1F181A020B28 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F2E13020B29 1
|
010203040506 03032CFE06162CFE1F2E13020B29 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F4589020B2A 1
|
010203040506 03032CFE06162CFE1F4589020B2A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F4627020B2B 1
|
010203040506 03032CFE06162CFE1F4627020B2B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1F5865020B2C 1
|
010203040506 03032CFE06162CFE1F5865020B2C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1FBB50020B2D 1
|
010203040506 03032CFE06162CFE1FBB50020B2D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1FC95C020B2E 1
|
010203040506 03032CFE06162CFE1FC95C020B2E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1FE765020B2F 1
|
010203040506 03032CFE06162CFE1FE765020B2F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE1FF8FA020B30 1
|
010203040506 03032CFE06162CFE1FF8FA020B30 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE201C7C020B31 1
|
010203040506 03032CFE06162CFE201C7C020B31 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE202B3D020B32 1
|
010203040506 03032CFE06162CFE202B3D020B32 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE20330C020B33 1
|
010203040506 03032CFE06162CFE20330C020B33 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE20A19B020B34 1
|
010203040506 03032CFE06162CFE20A19B020B34 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE20C95C020B35 1
|
010203040506 03032CFE06162CFE20C95C020B35 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE20CC2C020B36 1
|
010203040506 03032CFE06162CFE20CC2C020B36 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE213C8C020B37 1
|
010203040506 03032CFE06162CFE213C8C020B37 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE21521D020B38 1
|
010203040506 03032CFE06162CFE21521D020B38 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE21A04E020B39 1
|
010203040506 03032CFE06162CFE21A04E020B39 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE2D7A23020B3A 1
|
010203040506 03032CFE06162CFE2D7A23020B3A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE350000020B3B 1
|
010203040506 03032CFE06162CFE350000020B3B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE470000020B3C 1
|
010203040506 03032CFE06162CFE470000020B3C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE480000020B3D 1
|
010203040506 03032CFE06162CFE480000020B3D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE490000020B3E 1
|
010203040506 03032CFE06162CFE490000020B3E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5BA9B5020B3F 1
|
010203040506 03032CFE06162CFE5BA9B5020B3F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5BACD6020B40 1
|
010203040506 03032CFE06162CFE5BACD6020B40 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5BD6C9020B41 1
|
010203040506 03032CFE06162CFE5BD6C9020B41 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5BE3D4020B42 1
|
010203040506 03032CFE06162CFE5BE3D4020B42 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C0206020B43 1
|
010203040506 03032CFE06162CFE5C0206020B43 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C0C84020B44 1
|
010203040506 03032CFE06162CFE5C0C84020B44 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C4833020B45 1
|
010203040506 03032CFE06162CFE5C4833020B45 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C4A7E020B46 1
|
010203040506 03032CFE06162CFE5C4A7E020B46 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C55E7020B47 1
|
010203040506 03032CFE06162CFE5C55E7020B47 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C7CDC020B48 1
|
010203040506 03032CFE06162CFE5C7CDC020B48 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5C8AA5020B49 1
|
010203040506 03032CFE06162CFE5C8AA5020B49 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC900020B4A 1
|
010203040506 03032CFE06162CFE5CC900020B4A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC901020B4B 1
|
010203040506 03032CFE06162CFE5CC901020B4B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC902020B4C 1
|
010203040506 03032CFE06162CFE5CC902020B4C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC903020B4D 1
|
010203040506 03032CFE06162CFE5CC903020B4D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC904020B4E 1
|
010203040506 03032CFE06162CFE5CC904020B4E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC905020B4F 1
|
010203040506 03032CFE06162CFE5CC905020B4F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC906020B50 1
|
010203040506 03032CFE06162CFE5CC906020B50 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC907020B51 1
|
010203040506 03032CFE06162CFE5CC907020B51 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC908020B52 1
|
010203040506 03032CFE06162CFE5CC908020B52 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC909020B53 1
|
010203040506 03032CFE06162CFE5CC909020B53 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90A020B54 1
|
010203040506 03032CFE06162CFE5CC90A020B54 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90B020B55 1
|
010203040506 03032CFE06162CFE5CC90B020B55 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90C020B56 1
|
010203040506 03032CFE06162CFE5CC90C020B56 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90D020B57 1
|
010203040506 03032CFE06162CFE5CC90D020B57 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90E020B58 1
|
010203040506 03032CFE06162CFE5CC90E020B58 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC90F020B59 1
|
010203040506 03032CFE06162CFE5CC90F020B59 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC910020B5A 1
|
010203040506 03032CFE06162CFE5CC910020B5A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC911020B5B 1
|
010203040506 03032CFE06162CFE5CC911020B5B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC912020B5C 1
|
010203040506 03032CFE06162CFE5CC912020B5C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC913020B5D 1
|
010203040506 03032CFE06162CFE5CC913020B5D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC914020B5E 1
|
010203040506 03032CFE06162CFE5CC914020B5E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC915020B5F 1
|
010203040506 03032CFE06162CFE5CC915020B5F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC916020B60 1
|
010203040506 03032CFE06162CFE5CC916020B60 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC917020B61 1
|
010203040506 03032CFE06162CFE5CC917020B61 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC918020B62 1
|
010203040506 03032CFE06162CFE5CC918020B62 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC919020B63 1
|
010203040506 03032CFE06162CFE5CC919020B63 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91A020B64 1
|
010203040506 03032CFE06162CFE5CC91A020B64 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91B020B65 1
|
010203040506 03032CFE06162CFE5CC91B020B65 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91C020B66 1
|
010203040506 03032CFE06162CFE5CC91C020B66 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91D020B67 1
|
010203040506 03032CFE06162CFE5CC91D020B67 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91E020B68 1
|
010203040506 03032CFE06162CFE5CC91E020B68 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC91F020B69 1
|
010203040506 03032CFE06162CFE5CC91F020B69 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC920020B6A 1
|
010203040506 03032CFE06162CFE5CC920020B6A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC921020B6B 1
|
010203040506 03032CFE06162CFE5CC921020B6B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC922020B6C 1
|
010203040506 03032CFE06162CFE5CC922020B6C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC923020B6D 1
|
010203040506 03032CFE06162CFE5CC923020B6D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC924020B6E 1
|
010203040506 03032CFE06162CFE5CC924020B6E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC925020B6F 1
|
010203040506 03032CFE06162CFE5CC925020B6F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC926020B70 1
|
010203040506 03032CFE06162CFE5CC926020B70 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC927020B71 1
|
010203040506 03032CFE06162CFE5CC927020B71 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC928020B72 1
|
010203040506 03032CFE06162CFE5CC928020B72 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC929020B73 1
|
010203040506 03032CFE06162CFE5CC929020B73 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92A020B74 1
|
010203040506 03032CFE06162CFE5CC92A020B74 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92B020B75 1
|
010203040506 03032CFE06162CFE5CC92B020B75 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92C020B76 1
|
010203040506 03032CFE06162CFE5CC92C020B76 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92D020B77 1
|
010203040506 03032CFE06162CFE5CC92D020B77 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92E020B78 1
|
010203040506 03032CFE06162CFE5CC92E020B78 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC92F020B79 1
|
010203040506 03032CFE06162CFE5CC92F020B79 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC930020B7A 1
|
010203040506 03032CFE06162CFE5CC930020B7A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC931020B7B 1
|
010203040506 03032CFE06162CFE5CC931020B7B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC932020B7C 1
|
010203040506 03032CFE06162CFE5CC932020B7C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC933020B7D 1
|
010203040506 03032CFE06162CFE5CC933020B7D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC934020B7E 1
|
010203040506 03032CFE06162CFE5CC934020B7E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC935020B7F 1
|
010203040506 03032CFE06162CFE5CC935020B7F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC936020B80 1
|
010203040506 03032CFE06162CFE5CC936020B80 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC937020B81 1
|
010203040506 03032CFE06162CFE5CC937020B81 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC938020B82 1
|
010203040506 03032CFE06162CFE5CC938020B82 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC939020B83 1
|
010203040506 03032CFE06162CFE5CC939020B83 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93A020B84 1
|
010203040506 03032CFE06162CFE5CC93A020B84 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93B020B85 1
|
010203040506 03032CFE06162CFE5CC93B020B85 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93C020B86 1
|
010203040506 03032CFE06162CFE5CC93C020B86 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93D020B87 1
|
010203040506 03032CFE06162CFE5CC93D020B87 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93E020B88 1
|
010203040506 03032CFE06162CFE5CC93E020B88 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC93F020B89 1
|
010203040506 03032CFE06162CFE5CC93F020B89 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC940020B8A 1
|
010203040506 03032CFE06162CFE5CC940020B8A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC941020B8B 1
|
010203040506 03032CFE06162CFE5CC941020B8B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC942020B8C 1
|
010203040506 03032CFE06162CFE5CC942020B8C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC943020B8D 1
|
010203040506 03032CFE06162CFE5CC943020B8D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC944020B8E 1
|
010203040506 03032CFE06162CFE5CC944020B8E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CC945020B8F 1
|
010203040506 03032CFE06162CFE5CC945020B8F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE5CEE3C020B90 1
|
010203040506 03032CFE06162CFE5CEE3C020B90 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6AD226020B91 1
|
010203040506 03032CFE06162CFE6AD226020B91 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6B1C64020B92 1
|
010203040506 03032CFE06162CFE6B1C64020B92 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6B8C65020B93 1
|
010203040506 03032CFE06162CFE6B8C65020B93 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6B9304020B94 1
|
010203040506 03032CFE06162CFE6B9304020B94 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6BA5C3020B95 1
|
010203040506 03032CFE06162CFE6BA5C3020B95 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6C42C0020B96 1
|
010203040506 03032CFE06162CFE6C42C0020B96 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE6C4DE5020B97 1
|
010203040506 03032CFE06162CFE6C4DE5020B97 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE718FA4020B98 1
|
010203040506 03032CFE06162CFE718FA4020B98 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE72EF8D020B99 1
|
010203040506 03032CFE06162CFE72EF8D020B99 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE72FB00020B9A 1
|
010203040506 03032CFE06162CFE72FB00020B9A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE821F66020B9B 1
|
010203040506 03032CFE06162CFE821F66020B9B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE89BAD5020B9C 1
|
010203040506 03032CFE06162CFE89BAD5020B9C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8A31B7020B9D 1
|
010203040506 03032CFE06162CFE8A31B7020B9D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8A3D00020B9E 1
|
010203040506 03032CFE06162CFE8A3D00020B9E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8A3D01020B9F 1
|
010203040506 03032CFE06162CFE8A3D01020B9F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8A8F23020BA0 1
|
010203040506 03032CFE06162CFE8A8F23020BA0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8AADAE020BA1 1
|
010203040506 03032CFE06162CFE8AADAE020BA1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8B0A91020BA2 1
|
010203040506 03032CFE06162CFE8B0A91020BA2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8B5A7B020BA3 1
|
010203040506 03032CFE06162CFE8B5A7B020BA3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8B66AB020BA4 1
|
010203040506 03032CFE06162CFE8B66AB020BA4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8BB0A0020BA5 1
|
010203040506 03032CFE06162CFE8BB0A0020BA5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8BF79A020BA6 1
|
010203040506 03032CFE06162CFE8BF79A020BA6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8C07D2020BA7 1
|
010203040506 03032CFE06162CFE8C07D2020BA7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8C1706020BA8 1
|
010203040506 03032CFE06162CFE8C1706020BA8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8C4236020BA9 1
|
010203040506 03032CFE06162CFE8C4236020BA9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8C6B6A020BAA 1
|
010203040506 03032CFE06162CFE8C6B6A020BAA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8CAD81020BAB 1
|
010203040506 03032CFE06162CFE8CAD81020BAB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8CB05C020BAC 1
|
010203040506 03032CFE06162CFE8CB05C020BAC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8CD10F020BAD 1
|
010203040506 03032CFE06162CFE8CD10F020BAD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8D13B9020BAE 1
|
010203040506 03032CFE06162CFE8D13B9020BAE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8D16EA020BAF 1
|
010203040506 03032CFE06162CFE8D16EA020BAF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8D5B67020BB0 1
|
010203040506 03032CFE06162CFE8D5B67020BB0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8E14D7020BB1 1
|
010203040506 03032CFE06162CFE8E14D7020BB1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8E1996020BB2 1
|
010203040506 03032CFE06162CFE8E1996020BB2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8E4666020BB3 1
|
010203040506 03032CFE06162CFE8E4666020BB3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE8E5550020BB4 1
|
010203040506 03032CFE06162CFE8E5550020BB4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9101F0020BB5 1
|
010203040506 03032CFE06162CFE9101F0020BB5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9128CB020BB6 1
|
010203040506 03032CFE06162CFE9128CB020BB6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE913B0C020BB7 1
|
010203040506 03032CFE06162CFE913B0C020BB7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE915CFA020BB8 1
|
010203040506 03032CFE06162CFE915CFA020BB8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9171BE020BB9 1
|
010203040506 03032CFE06162CFE9171BE020BB9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE917E46020BBA 1
|
010203040506 03032CFE06162CFE917E46020BBA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA00020BBB 1
|
010203040506 03032CFE06162CFE91AA00020BBB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA01020BBC 1
|
010203040506 03032CFE06162CFE91AA01020BBC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA02020BBD 1
|
010203040506 03032CFE06162CFE91AA02020BBD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA03020BBE 1
|
010203040506 03032CFE06162CFE91AA03020BBE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA04020BBF 1
|
010203040506 03032CFE06162CFE91AA04020BBF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91AA05020BC0 1
|
010203040506 03032CFE06162CFE91AA05020BC0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91BD38020BC1 1
|
010203040506 03032CFE06162CFE91BD38020BC1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91C813020BC2 1
|
010203040506 03032CFE06162CFE91C813020BC2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE91DABC020BC3 1
|
010203040506 03032CFE06162CFE91DABC020BC3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE92255E020BC4 1
|
010203040506 03032CFE06162CFE92255E020BC4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE92BBBD020BC5 1
|
010203040506 03032CFE06162CFE92BBBD020BC5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE989D0A020BC6 1
|
010203040506 03032CFE06162CFE989D0A020BC6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9939BC020BC7 1
|
010203040506 03032CFE06162CFE9939BC020BC7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE994374020BC8 1
|
010203040506 03032CFE06162CFE994374020BC8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE997B4A020BC9 1
|
010203040506 03032CFE06162CFE997B4A020BC9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE99C87B020BCA 1
|
010203040506 03032CFE06162CFE99C87B020BCA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE99D7EA020BCB 1
|
010203040506 03032CFE06162CFE99D7EA020BCB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE99F098020BCC 1
|
010203040506 03032CFE06162CFE99F098020BCC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9A408A020BCD 1
|
010203040506 03032CFE06162CFE9A408A020BCD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9A9BDD020BCE 1
|
010203040506 03032CFE06162CFE9A9BDD020BCE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9ADB11020BCF 1
|
010203040506 03032CFE06162CFE9ADB11020BCF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9AEEA4020BD0 1
|
010203040506 03032CFE06162CFE9AEEA4020BD0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9B7339020BD1 1
|
010203040506 03032CFE06162CFE9B7339020BD1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9B735A020BD2 1
|
010203040506 03032CFE06162CFE9B735A020BD2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9B9872020BD3 1
|
010203040506 03032CFE06162CFE9B9872020BD3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9BC64D020BD4 1
|
010203040506 03032CFE06162CFE9BC64D020BD4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9BE931020BD5 1
|
010203040506 03032CFE06162CFE9BE931020BD5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C0AF7020BD6 1
|
010203040506 03032CFE06162CFE9C0AF7020BD6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C3997020BD7 1
|
010203040506 03032CFE06162CFE9C3997020BD7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C4058020BD8 1
|
010203040506 03032CFE06162CFE9C4058020BD8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C6BC0020BD9 1
|
010203040506 03032CFE06162CFE9C6BC0020BD9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C888B020BDA 1
|
010203040506 03032CFE06162CFE9C888B020BDA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9C98DB020BDB 1
|
010203040506 03032CFE06162CFE9C98DB020BDB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CA277020BDC 1
|
010203040506 03032CFE06162CFE9CA277020BDC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CB5F3020BDD 1
|
010203040506 03032CFE06162CFE9CB5F3020BDD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CB881020BDE 1
|
010203040506 03032CFE06162CFE9CB881020BDE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CD0F3020BDF 1
|
010203040506 03032CFE06162CFE9CD0F3020BDF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CE3C7020BE0 1
|
010203040506 03032CFE06162CFE9CE3C7020BE0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CEFD1020BE1 1
|
010203040506 03032CFE06162CFE9CEFD1020BE1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9CF08F020BE2 1
|
010203040506 03032CFE06162CFE9CF08F020BE2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9D00A6020BE3 1
|
010203040506 03032CFE06162CFE9D00A6020BE3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9D7D42020BE4 1
|
010203040506 03032CFE06162CFE9D7D42020BE4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFE9DB896020BE5 1
|
010203040506 03032CFE06162CFE9DB896020BE5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA7E52B020BE6 1
|
010203040506 03032CFE06162CFEA7E52B020BE6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA7EF76020BE7 1
|
010203040506 03032CFE06162CFEA7EF76020BE7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8001A020BE8 1
|
010203040506 03032CFE06162CFEA8001A020BE8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA83C10020BE9 1
|
010203040506 03032CFE06162CFEA83C10020BE9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8658F020BEA 1
|
010203040506 03032CFE06162CFEA8658F020BEA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8845A020BEB 1
|
010203040506 03032CFE06162CFEA8845A020BEB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA88B69020BEC 1
|
010203040506 03032CFE06162CFEA88B69020BEC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8A00E020BED 1
|
010203040506 03032CFE06162CFEA8A00E020BED DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8A72A020BEE 1
|
010203040506 03032CFE06162CFEA8A72A020BEE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8C636020BEF 1
|
010203040506 03032CFE06162CFEA8C636020BEF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8CAAD020BF0 1
|
010203040506 03032CFE06162CFEA8CAAD020BF0 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8E353020BF1 1
|
010203040506 03032CFE06162CFEA8E353020BF1 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA8F96D020BF2 1
|
010203040506 03032CFE06162CFEA8F96D020BF2 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA90358020BF3 1
|
010203040506 03032CFE06162CFEA90358020BF3 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA92498020BF4 1
|
010203040506 03032CFE06162CFEA92498020BF4 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEA9394A020BF5 1
|
010203040506 03032CFE06162CFEA9394A020BF5 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC6936A020BF6 1
|
010203040506 03032CFE06162CFEC6936A020BF6 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC69AFD020BF7 1
|
010203040506 03032CFE06162CFEC69AFD020BF7 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC6ABEA020BF8 1
|
010203040506 03032CFE06162CFEC6ABEA020BF8 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC6EC5F020BF9 1
|
010203040506 03032CFE06162CFEC6EC5F020BF9 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC7736C020BFA 1
|
010203040506 03032CFE06162CFEC7736C020BFA DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC79B91020BFB 1
|
010203040506 03032CFE06162CFEC79B91020BFB DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC7A267020BFC 1
|
010203040506 03032CFE06162CFEC7A267020BFC DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC7D620020BFD 1
|
010203040506 03032CFE06162CFEC7D620020BFD DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC7FBCC020BFE 1
|
010203040506 03032CFE06162CFEC7FBCC020BFE DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC8162A020BFF 1
|
010203040506 03032CFE06162CFEC8162A020BFF DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC85D7A020C00 1
|
010203040506 03032CFE06162CFEC85D7A020C00 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC8777E020C01 1
|
010203040506 03032CFE06162CFEC8777E020C01 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC878AA020C02 1
|
010203040506 03032CFE06162CFEC878AA020C02 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC8C641020C03 1
|
010203040506 03032CFE06162CFEC8C641020C03 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC8D335020C04 1
|
010203040506 03032CFE06162CFEC8D335020C04 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC8E228020C05 1
|
010203040506 03032CFE06162CFEC8E228020C05 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC9186B020C06 1
|
010203040506 03032CFE06162CFEC9186B020C06 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEC9836A020C07 1
|
010203040506 03032CFE06162CFEC9836A020C07 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECA7030020C08 1
|
010203040506 03032CFE06162CFECA7030020C08 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECAB6B8020C09 1
|
010203040506 03032CFE06162CFECAB6B8020C09 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECAF511020C0A 1
|
010203040506 03032CFE06162CFECAF511020C0A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECB093B020C0B 1
|
010203040506 03032CFE06162CFECB093B020C0B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECB529D020C0C 1
|
010203040506 03032CFE06162CFECB529D020C0C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECC438E020C0D 1
|
010203040506 03032CFE06162CFECC438E020C0D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECC5F29020C0E 1
|
010203040506 03032CFE06162CFECC5F29020C0E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECC754F020C0F 1
|
010203040506 03032CFE06162CFECC754F020C0F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECC93A5020C10 1
|
010203040506 03032CFE06162CFECC93A5020C10 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECCBB7E020C11 1
|
010203040506 03032CFE06162CFECCBB7E020C11 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFECD8256020C12 1
|
010203040506 03032CFE06162CFECD8256020C12 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED446A7020C13 1
|
010203040506 03032CFE06162CFED446A7020C13 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED5A59E020C14 1
|
010203040506 03032CFE06162CFED5A59E020C14 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED5B5F7020C15 1
|
010203040506 03032CFE06162CFED5B5F7020C15 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED5C6CE020C16 1
|
010203040506 03032CFE06162CFED5C6CE020C16 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED654CD020C17 1
|
010203040506 03032CFE06162CFED654CD020C17 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED65F4E020C18 1
|
010203040506 03032CFE06162CFED65F4E020C18 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED69B2B020C19 1
|
010203040506 03032CFE06162CFED69B2B020C19 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED6C195020C1A 1
|
010203040506 03032CFE06162CFED6C195020C1A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED6E870020C1B 1
|
010203040506 03032CFE06162CFED6E870020C1B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED6EE84020C1C 1
|
010203040506 03032CFE06162CFED6EE84020C1C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED7102F020C1D 1
|
010203040506 03032CFE06162CFED7102F020C1D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED7E3EB020C1E 1
|
010203040506 03032CFE06162CFED7E3EB020C1E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED8058C020C1F 1
|
010203040506 03032CFE06162CFED8058C020C1F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED820EA020C20 1
|
010203040506 03032CFE06162CFED820EA020C20 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED87A3E020C21 1
|
010203040506 03032CFE06162CFED87A3E020C21 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED8F3BA020C22 1
|
010203040506 03032CFE06162CFED8F3BA020C22 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED8F4E8020C23 1
|
010203040506 03032CFE06162CFED8F4E8020C23 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED90617020C24 1
|
010203040506 03032CFE06162CFED90617020C24 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED933A7020C25 1
|
010203040506 03032CFE06162CFED933A7020C25 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED9414F020C26 1
|
010203040506 03032CFE06162CFED9414F020C26 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED97EBA020C27 1
|
010203040506 03032CFE06162CFED97EBA020C27 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFED9964B020C28 1
|
010203040506 03032CFE06162CFED9964B020C28 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDA0F83020C29 1
|
010203040506 03032CFE06162CFEDA0F83020C29 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDA4577020C2A 1
|
010203040506 03032CFE06162CFEDA4577020C2A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDA5200020C2B 1
|
010203040506 03032CFE06162CFEDA5200020C2B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDAD3A6020C2C 1
|
010203040506 03032CFE06162CFEDAD3A6020C2C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDADE43020C2D 1
|
010203040506 03032CFE06162CFEDADE43020C2D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDAE096020C2E 1
|
010203040506 03032CFE06162CFEDAE096020C2E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDB8AC7020C2F 1
|
010203040506 03032CFE06162CFEDB8AC7020C2F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDBE5B1020C30 1
|
010203040506 03032CFE06162CFEDBE5B1020C30 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDC5249020C31 1
|
010203040506 03032CFE06162CFEDC5249020C31 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDCF33C020C32 1
|
010203040506 03032CFE06162CFEDCF33C020C32 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDD4EC0020C33 1
|
010203040506 03032CFE06162CFEDD4EC0020C33 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDE215D020C34 1
|
010203040506 03032CFE06162CFEDE215D020C34 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDE577F020C35 1
|
010203040506 03032CFE06162CFEDE577F020C35 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDEC04C020C36 1
|
010203040506 03032CFE06162CFEDEC04C020C36 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDEDD6F020C37 1
|
010203040506 03032CFE06162CFEDEDD6F020C37 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDEE8C0020C38 1
|
010203040506 03032CFE06162CFEDEE8C0020C38 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDEEA86020C39 1
|
010203040506 03032CFE06162CFEDEEA86020C39 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDEF234020C3A 1
|
010203040506 03032CFE06162CFEDEF234020C3A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDF01E3020C3B 1
|
010203040506 03032CFE06162CFEDF01E3020C3B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDF271C020C3C 1
|
010203040506 03032CFE06162CFEDF271C020C3C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDF42DE020C3D 1
|
010203040506 03032CFE06162CFEDF42DE020C3D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDF4B02020C3E 1
|
010203040506 03032CFE06162CFEDF4B02020C3E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDF9BA4020C3F 1
|
010203040506 03032CFE06162CFEDF9BA4020C3F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEDFD433020C40 1
|
010203040506 03032CFE06162CFEDFD433020C40 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE020C1020C41 1
|
010203040506 03032CFE06162CFEE020C1020C41 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE06116020C42 1
|
010203040506 03032CFE06162CFEE06116020C42 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE07634020C43 1
|
010203040506 03032CFE06162CFEE07634020C43 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE09172020C44 1
|
010203040506 03032CFE06162CFEE09172020C44 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE4E457020C45 1
|
010203040506 03032CFE06162CFEE4E457020C45 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE5440B020C46 1
|
010203040506 03032CFE06162CFEE5440B020C46 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE57363020C47 1
|
010203040506 03032CFE06162CFEE57363020C47 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE57B57020C48 1
|
010203040506 03032CFE06162CFEE57B57020C48 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE5B4B0020C49 1
|
010203040506 03032CFE06162CFEE5B4B0020C49 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE5B91B020C4A 1
|
010203040506 03032CFE06162CFEE5B91B020C4A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE5E2E9020C4B 1
|
010203040506 03032CFE06162CFEE5E2E9020C4B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE64613020C4C 1
|
010203040506 03032CFE06162CFEE64613020C4C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE64CC6020C4D 1
|
010203040506 03032CFE06162CFEE64CC6020C4D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE69877020C4E 1
|
010203040506 03032CFE06162CFEE69877020C4E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE6E37E020C4F 1
|
010203040506 03032CFE06162CFEE6E37E020C4F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE6E771020C50 1
|
010203040506 03032CFE06162CFEE6E771020C50 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE6E8B8020C51 1
|
010203040506 03032CFE06162CFEE6E8B8020C51 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEE750CE020C52 1
|
010203040506 03032CFE06162CFEE750CE020C52 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00000020C53 1
|
010203040506 03032CFE06162CFEF00000020C53 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00001020C54 1
|
010203040506 03032CFE06162CFEF00001020C54 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00002020C55 1
|
010203040506 03032CFE06162CFEF00002020C55 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00200020C56 1
|
010203040506 03032CFE06162CFEF00200020C56 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00201020C57 1
|
010203040506 03032CFE06162CFEF00201020C57 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00202020C58 1
|
010203040506 03032CFE06162CFEF00202020C58 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00203020C59 1
|
010203040506 03032CFE06162CFEF00203020C59 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00204020C5A 1
|
010203040506 03032CFE06162CFEF00204020C5A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00205020C5B 1
|
010203040506 03032CFE06162CFEF00205020C5B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00206020C5C 1
|
010203040506 03032CFE06162CFEF00206020C5C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00207020C5D 1
|
010203040506 03032CFE06162CFEF00207020C5D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00208020C5E 1
|
010203040506 03032CFE06162CFEF00208020C5E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00209020C5F 1
|
010203040506 03032CFE06162CFEF00209020C5F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020A020C60 1
|
010203040506 03032CFE06162CFEF0020A020C60 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020B020C61 1
|
010203040506 03032CFE06162CFEF0020B020C61 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020C020C62 1
|
010203040506 03032CFE06162CFEF0020C020C62 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020D020C63 1
|
010203040506 03032CFE06162CFEF0020D020C63 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020E020C64 1
|
010203040506 03032CFE06162CFEF0020E020C64 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF0020F020C65 1
|
010203040506 03032CFE06162CFEF0020F020C65 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00210020C66 1
|
010203040506 03032CFE06162CFEF00210020C66 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00211020C67 1
|
010203040506 03032CFE06162CFEF00211020C67 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00212020C68 1
|
010203040506 03032CFE06162CFEF00212020C68 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00213020C69 1
|
010203040506 03032CFE06162CFEF00213020C69 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00214020C6A 1
|
010203040506 03032CFE06162CFEF00214020C6A DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00215020C6B 1
|
010203040506 03032CFE06162CFEF00215020C6B DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00300020C6C 1
|
010203040506 03032CFE06162CFEF00300020C6C DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00301020C6D 1
|
010203040506 03032CFE06162CFEF00301020C6D DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00302020C6E 1
|
010203040506 03032CFE06162CFEF00302020C6E DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00303020C6F 1
|
010203040506 03032CFE06162CFEF00303020C6F DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00304020C70 1
|
010203040506 03032CFE06162CFEF00304020C70 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00305020C71 1
|
010203040506 03032CFE06162CFEF00305020C71 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00306020C72 1
|
010203040506 03032CFE06162CFEF00306020C72 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00307020C73 1
|
010203040506 03032CFE06162CFEF00307020C73 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00308020C74 1
|
010203040506 03032CFE06162CFEF00308020C74 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00309020C75 1
|
010203040506 03032CFE06162CFEF00309020C75 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00400020C76 1
|
010203040506 03032CFE06162CFEF00400020C76 DISCOVERY 1
|
||||||
010203040506 03032CFE06162CFEF00E97020C77 1
|
010203040506 03032CFE06162CFEF00E97020C77 DISCOVERY 1
|
@@ -1 +1 @@
|
|||||||
010203040506 00112233445566778899AABBCCDDEEFF 1000
|
010203040506 00112233445566778899AABBCCDDEEFF DISCOVERY 1000
|
@@ -1 +1 @@
|
|||||||
010203040506 190953445220426c7565746f6f7468204c6f7720456e65726779 1000
|
010203040506 190953445220426c7565746f6f7468204c6f7720456e65726779 DISCOVERY 1000
|
Reference in New Issue
Block a user