From 867539ce9c01c3f2eef0eba08f7a83f93e1f2339 Mon Sep 17 00:00:00 2001 From: Arjan Onwezen Date: Wed, 19 Jan 2022 11:01:38 -0500 Subject: [PATCH] centralize-db-retrieval-functions --- firmware/application/CMakeLists.txt | 1 + firmware/application/apps/ui_adsb_rx.cpp | 155 +++++++---------------- firmware/application/apps/ui_adsb_rx.hpp | 32 +++-- firmware/application/database.cpp | 97 ++++++++++++++ firmware/application/database.hpp | 88 +++++++++++++ 5 files changed, 251 insertions(+), 122 deletions(-) create mode 100644 firmware/application/database.cpp create mode 100644 firmware/application/database.hpp diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index c4b30fe4..a422aaaf 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -159,6 +159,7 @@ set(CPPSRC capture_thread.cpp clock_manager.cpp core_control.cpp + database.cpp de_bruijn.cpp #emu_cc1101.cpp rfm69.cpp diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 0d177917..cb1f26a3 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -107,11 +107,7 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView( const std::function on_close ) : entry_copy(entry), on_close_(on_close) -{ - char file_buffer[32] { 0 }; - bool found = false; - size_t number_of_icao_codes = 0; - std::string icao_code; +{ add_children({ &labels, @@ -130,46 +126,22 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView( std::unique_ptr logger { }; //update(entry_copy); + + icao_code = to_string_hex(entry_copy.ICAO_address, 6); text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6)); - // Try getting the aircraft information from icao24.db - auto result = db_file.open("ADSB/icao24.db"); - if (!result.is_valid()) { - // determine number of ICAO24 codes in file, total size / (single index + record size) - number_of_icao_codes = (db_file.size() / 153); - icao_code = to_string_hex(entry_copy.ICAO_address, 6); - - // binary search - int first = 0, // First search element - last = number_of_icao_codes - 1, // Last search element - middle, // Mid point of search - position = -1; // Position of search value - while (!found && first <= last) { - middle = (first + last) / 2; // Calculate mid point - db_file.seek(middle * 7); - db_file.read(file_buffer, 6); - if (file_buffer == icao_code) { // If value is found at mid - found = true; - position = middle; - } - else if (file_buffer > icao_code) // If value is in lower half - last = middle - 1; - else - first = middle + 1; // If value is in upper half - } - - if (position > -1) { - db_file.seek((number_of_icao_codes * 7) + (position * 146)); // seek starting after index - db_file.read(file_buffer, 9); - text_registration.set(file_buffer); - db_file.read(file_buffer, 33); - text_manufacturer.set(file_buffer); - db_file.read(file_buffer, 33); - text_model.set(file_buffer); - db_file.read(file_buffer, 5); // ICAO type decripton - if(strlen(file_buffer) == 3) { - switch(file_buffer[0]) { + return_code = db.retrieve_aircraft_record(&aircraft_record, icao_code); + switch(return_code) { + case DATABASE_RECORD_FOUND: + text_registration.set(aircraft_record.aircraft_registration); + text_manufacturer.set(aircraft_record.aircraft_manufacturer); + text_model.set(aircraft_record.aircraft_model); + text_owner.set(aircraft_record.aircraft_owner); + text_operator.set(aircraft_record.aircraft_operator); + // Check for ICAO type, e.g. L2J + if(strlen(aircraft_record.icao_type) == 3) { + switch(aircraft_record.icao_type[0]) { case 'L': text_type.set("Landplane"); break; @@ -189,8 +161,8 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView( text_type.set("Tilt-wing aircraft"); break; } - text_number_of_engines.set(std::string(1, file_buffer[1])); - switch(file_buffer[2]) { + text_number_of_engines.set(std::string(1, aircraft_record.icao_type[1])); + switch(aircraft_record.icao_type[2]) { case 'P': text_engine_type.set("Piston engine"); break; @@ -206,30 +178,22 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView( } } - // check for ICAO type designator - else if(strlen(file_buffer) == 4) { - if(strcmp(file_buffer,"SHIP") == 0) text_type.set("Airship"); - else if(strcmp(file_buffer,"BALL") == 0) text_type.set("Balloon"); - else if(strcmp(file_buffer,"GLID") == 0) text_type.set("Glider / sailplane"); - else if(strcmp(file_buffer,"ULAC") == 0) text_type.set("Micro/ultralight aircraft"); - else if(strcmp(file_buffer,"GYRO") == 0) text_type.set("Micro/ultralight autogyro"); - else if(strcmp(file_buffer,"UHEL") == 0) text_type.set("Micro/ultralight helicopter"); - else if(strcmp(file_buffer,"SHIP") == 0) text_type.set("Airship"); - else if(strcmp(file_buffer,"PARA") == 0) text_type.set("Powered parachute/paraplane"); - } - db_file.read(file_buffer, 33); - text_owner.set(file_buffer); - db_file.read(file_buffer, 33); - text_operator.set(file_buffer); - } else { - text_registration.set("Unknown"); - text_manufacturer.set("Unknown"); - } - } else { - text_manufacturer.set("No icao24.db file"); + // Check for ICAO type designator + else if(strlen(aircraft_record.icao_type) == 4) { + if(strcmp(aircraft_record.icao_type,"SHIP") == 0) text_type.set("Airship"); + else if(strcmp(aircraft_record.icao_type,"BALL") == 0) text_type.set("Balloon"); + else if(strcmp(aircraft_record.icao_type,"GLID") == 0) text_type.set("Glider / sailplane"); + else if(strcmp(aircraft_record.icao_type,"ULAC") == 0) text_type.set("Micro/ultralight aircraft"); + else if(strcmp(aircraft_record.icao_type,"GYRO") == 0) text_type.set("Micro/ultralight autogyro"); + else if(strcmp(aircraft_record.icao_type,"UHEL") == 0) text_type.set("Micro/ultralight helicopter"); + else if(strcmp(aircraft_record.icao_type,"SHIP") == 0) text_type.set("Airship"); + else if(strcmp(aircraft_record.icao_type,"PARA") == 0) text_type.set("Powered parachute/paraplane"); + } + break; + case DATABASE_NOT_FOUND: + text_manufacturer.set("No icao24.db file"); + break; } - - button_close.on_select = [&nav](Button&){ nav.pop(); }; @@ -275,11 +239,7 @@ ADSBRxDetailsView::ADSBRxDetailsView( ) : entry_copy(entry), on_close_(on_close) { - char file_buffer[32] { 0 }; - bool found = false; - size_t number_of_airlines = 0; - std::string airline_code; - + add_children({ &labels, &text_icao_address, @@ -300,46 +260,19 @@ ADSBRxDetailsView::ADSBRxDetailsView( // The following won't (shouldn't !) change for a given airborne aircraft // Try getting the airline's name from airlines.db - auto result = db_file.open("ADSB/airlines.db"); - if (!result.is_valid()) { - // Search for 3-letter code - number_of_airlines = (db_file.size() / 68); // determine number of airlines in file - airline_code = entry_copy.callsign.substr(0, 3); - - // binary search - int first = 0, // First search element - last = number_of_airlines - 1, // Last search element - middle, // Mid point of search - position = -1; // Position of search value - while (!found && first <= last) { - middle = (first + last) / 2; // Calculate mid point - db_file.seek(middle * 4); - db_file.read(file_buffer, 3); - if (file_buffer == airline_code) { // If value is found at mid - found = true; - position = middle; - } - else if (file_buffer > airline_code) // If value is in lower half - last = middle - 1; - else - first = middle + 1; // If value is in upper half - } - - if (position > -1) { - db_file.seek((number_of_airlines * 4) + (position << 6)); // seek starting after index - db_file.read(file_buffer, 32); - text_airline.set(file_buffer); - db_file.read(file_buffer, 32); - text_country.set(file_buffer); - } else { - text_airline.set("Unknown"); - text_country.set("Unknown"); - } - } else { - text_airline.set("No airlines.db file"); - text_country.set("No airlines.db file"); + airline_code = entry_copy.callsign.substr(0, 3); + return_code = db.retrieve_airline_record(&airline_record, airline_code); + switch(return_code) { + case DATABASE_RECORD_FOUND: + text_airline.set(airline_record.airline); + text_country.set(airline_record.country); + break; + case DATABASE_NOT_FOUND: + text_airline.set("No airlines.db file"); + break; } - + + text_callsign.set(entry_copy.callsign); text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6)); diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index e8b637cc..e9ee91cb 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -27,6 +27,7 @@ #include "ui_font_fixed_8x16.hpp" #include "file.hpp" +#include "database.hpp" #include "recent_entries.hpp" #include "log_file.hpp" #include "adsb.hpp" @@ -176,13 +177,17 @@ public: std::string title() const override { return "AC Details"; }; AircraftRecentEntry get_current_entry() { return entry_copy; } + + std::database::AircraftDBRecord aircraft_record = {}; private: - AircraftRecentEntry entry_copy { 0 }; - std::function on_close_ { }; - bool send_updates { false }; - File db_file { }; - + AircraftRecentEntry entry_copy { 0 }; + std::function on_close_ { }; + bool send_updates { false }; + std::database db; + std::string icao_code = ""; + int return_code = 0; + Labels labels { { { 0 * 8, 1 * 16 }, "ICAO:", Color::light_grey() }, { { 0 * 8, 2 * 16 }, "Registration:", Color::light_grey() }, @@ -264,14 +269,19 @@ public: std::string title() const override { return "Details"; }; AircraftRecentEntry get_current_entry() { return entry_copy; } + + + std::database::AirlinesDBRecord airline_record = {}; private: - AircraftRecentEntry entry_copy { 0 }; - std::function on_close_ { }; - GeoMapView* geomap_view { nullptr }; - ADSBRxAircraftDetailsView* aircraft_details_view { nullptr }; - bool send_updates { false }; - File db_file { }; + AircraftRecentEntry entry_copy { 0 }; + std::function on_close_ { }; + GeoMapView* geomap_view { nullptr }; + ADSBRxAircraftDetailsView* aircraft_details_view { nullptr }; + bool send_updates { false }; + std::database db; + std::string airline_code = ""; + int return_code = 0; Labels labels { { { 0 * 8, 1 * 16 }, "ICAO:", Color::light_grey() }, diff --git a/firmware/application/database.cpp b/firmware/application/database.cpp new file mode 100644 index 00000000..edac3ef7 --- /dev/null +++ b/firmware/application/database.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * Copyright (C) 2022 Arjan Onwezen + * + * 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 "database.hpp" +#include "file.hpp" +#include + +namespace std { + + +int database::retrieve_airline_record(AirlinesDBRecord* record, std::string search_term){ + + file_path = "ADSB/airlines.db"; + index_item_length = 4; + record_length = 64; + + result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term); + + return(result); +} + +int database::retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term){ + + file_path = "ADSB/icao24.db"; + index_item_length = 7; + record_length = 146; + + result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term); + + return(result); +} + + + +int database::retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term) +{ + + auto result = db_file.open(file_path); + if (!result.is_valid()) { + number_of_records = (db_file.size() / (index_item_length + record_length)); // determine number of records in file + // binary search tree + int first = 0, // First search element + last = number_of_records - 1, // Last search element + middle, // Mid point of search + position = -1; // Position of search value + + while (!found && first <= last) { + middle = (first + last) / 2; // Calculate mid point + db_file.seek(middle * index_item_length); + db_file.read(file_buffer, search_term.length()); + if (file_buffer == search_term) { // If value is found at mid + found = true; + position = middle; + } + else if (file_buffer > search_term) // If value is in lower half + last = middle - 1; + else + first = middle + 1; // If value is in upper half + } + + if(found == true) { + + db_file.seek((number_of_records * index_item_length) + (position * record_length)); // seek starting after index + db_file.read(record, record_length); + return(DATABASE_RECORD_FOUND); + } + else { + return(DATABASE_RECORD_NOT_FOUND); + } + + } + else return(DATABASE_NOT_FOUND); + +} + + +} /* namespace std */ diff --git a/firmware/application/database.hpp b/firmware/application/database.hpp new file mode 100644 index 00000000..7159f6b1 --- /dev/null +++ b/firmware/application/database.hpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * Copyright (C) 2022 Arjan Onwezen + * + * 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. + */ + +#ifndef __DATABASE_H__ +#define __DATABASE_H__ + + +#include +#include +#include + +#include "file.hpp" + + + +namespace std { +class database { + + + +public: + +#define DATABASE_RECORD_FOUND 0 // record found in database +#define DATABASE_NOT_FOUND -1 // database not found / could not be opened +#define DATABASE_RECORD_NOT_FOUND -2 // record could not be found in database + + struct AirlinesDBRecord { + char airline[32]; // airline name + char country[32]; // country name + }; + + int retrieve_airline_record(AirlinesDBRecord* record, std::string search_term); + + struct AircraftDBRecord { + char aircraft_registration[9]; // aircraft registration + char aircraft_manufacturer[33]; // aircraft manufacturer + char aircraft_model[33]; // aircraft model + char icao_type[5]; // ICAO type descripton or when unavailable ICAO type designator + char aircraft_owner[33]; // aircraft owner + char aircraft_operator[33]; // aircraft operator + + }; + + int retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term); + +private: + string file_path = ""; // path inclusing filename + int index_item_length = 0; // length of index item + int record_length = 0; // length of record + + File db_file { }; + int number_of_records = 0; + int position = 0; + + char file_buffer[32] { 0 }; + bool found = false; + + int result = 0; + + int retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term); + + +}; +} // namespace std + + + +#endif/*__DATABASE_H__*/