Skip to content

Commit

Permalink
Remove QSql dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy committed Jan 15, 2025
1 parent 8680a54 commit 0620d2c
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 219 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt6 COMPONENTS Concurrent Core Sql)
find_package(Qt6 COMPONENTS Concurrent Core)
find_package(PkgConfig)

find_path(ZeroMQ_INCLUDE_DIR NAMES zmq.h PATHS ${PC_ZeroMQ_INCLUDE_DIRS})
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ TBA

## TODO
-[ ] Implement test harness that streams audio from audio-out into a ZeroMQ topic for samples testing
-[ ] Cut out plane registration database code from AeroL
-[x] Cut out plane registration database code from AeroL
-[ ] Implement ACARS frame forwarding functionality
-[ ] Implement translation of ACARSItem to JSON
-[ ] Long term test to ensure processor and memory usage is within expectations
Expand All @@ -20,3 +20,6 @@ Other configurations not mentioned may work but below is the configuration used
* ZeroMQ 4.3.5
* libcorrect (commit f5a28c74fba7a99736fe49d3a5243eca29517ae9)
* QT 6.4+

## Credits
* JAERO team
2 changes: 1 addition & 1 deletion decode/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ find_library(libcorrect_LIBRARIES NAMES correct PATHS ${PC_libcorrect_LIBRARY_DI
include_directories(${ZeroMQ_INCLUDE_DIRS} ${COMMON_INCLUDE_DIR})

add_executable(aero-decode main.cpp decode.cpp mskdemodulator.cpp oqpskdemodulator.cpp DSP.cpp jfft.cpp coarsefreqestimate.cpp fftwrapper.cpp aerol.cpp jconvolutionalcodec.cpp databasetext.cpp ${COMMON_NOTIFIER_SOURCE_FILE} ${COMMON_LOGGER_SOURCE_FILE})
target_link_libraries(aero-decode PRIVATE ${ZeroMQ_LIBRARIES} ${libcorrect_LIBRARIES} Qt6::Concurrent Qt6::Core Qt6::Sql)
target_link_libraries(aero-decode PRIVATE ${ZeroMQ_LIBRARIES} ${libcorrect_LIBRARIES} Qt6::Concurrent Qt6::Core)

208 changes: 52 additions & 156 deletions decode/databasetext.cpp
Original file line number Diff line number Diff line change
@@ -1,176 +1,72 @@
#include "databasetext.h"

#include <QFileInfo>
#include <QDir>
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>

DataBaseText *dbtext=NULL;
DataBaseText *dbtext = NULL;

DataBaseTextUser::DataBaseTextUser(QObject *parent ):QObject(parent)
{
if(dbtext==NULL)dbtext=new DataBaseText(parent);
refcounter=0;
map.clear();
DataBaseTextUser::DataBaseTextUser(QObject *parent) : QObject(parent) {
if (dbtext == NULL)
dbtext = new DataBaseText(parent);
refcounter = 0;
map.clear();
}

DataBaseTextUser::~DataBaseTextUser()
{
clear();
DataBaseTextUser::~DataBaseTextUser() { clear(); }

void DataBaseTextUser::clear() {
QList<DBase *> list = map.values();
for (int i = 0; i < list.size(); i++) {
delete list[i];
}
map.clear();
}

void DataBaseTextUser::clear()
{
QList<DBase*> list=map.values();
for(int i=0;i<list.size();i++)
{
delete list[i];
}
DBase *DataBaseTextUser::getuserdata(int ref) {
int cnt = map.count(ref);
if (cnt == 0)
return NULL;
else if (cnt > 1) {
qDebug() << "Error more than one entry in DataBaseTextUser map";
map.clear();
return NULL;
}
DBase *obj = map.value(ref);
map.remove(ref);
return obj;
}

DBase* DataBaseTextUser::getuserdata(int ref)
{
int cnt=map.count(ref);
if(cnt==0)return NULL;
else if(cnt>1)
{
qDebug()<<"Error more than one entry in DataBaseTextUser map";
map.clear();
return NULL;
}
DBase *obj = map.value(ref);
map.remove(ref);
return obj;
}
// QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));

void DataBaseTextUser::request(const QString &dirname, const QString &AEStext,DBase* userdata)
{
if(userdata==NULL)
{
dbtext->asyncDbLookupFromAES(dirname,AEStext,-1,this,"result");
return;
}
if(refcounter<0)refcounter=0;
refcounter++;refcounter%=DataBaseTextUser_MAX_PACKETS_IN_QUEUE;
DBase *obj;
while( (obj=map.take(refcounter))!=NULL )delete obj;
map.insert(refcounter,userdata);
emit dbtext->asyncDbLookupFromAES(dirname,AEStext,refcounter,this,"result");
void DataBaseTextUser::request(const QString &dirname, const QString &AEStext,
DBase *userdata) {
QStringList values;

if (userdata == NULL) {
values.push_back("userdata is NULL");
emit result(false, -1, values);

return;
}
if (refcounter < 0)
refcounter = 0;
refcounter++;
refcounter %= DataBaseTextUser_MAX_PACKETS_IN_QUEUE;
DBase *obj;
while ((obj = map.take(refcounter)) != NULL)
delete obj;
map.insert(refcounter, userdata);
emit result(false, refcounter, values);
}

//------------

DataBaseText::DataBaseText(QObject *parent) : QObject(parent)
{
DataBaseWorkerText *worker = new DataBaseWorkerText;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &DataBaseText::asyncDbLookupFromAES, worker, &DataBaseWorkerText::DbLookupFromAES);
workerThread.start();
DataBaseText::DataBaseText(QObject *parent) : QObject(parent) {
workerThread.start();
}

DataBaseText::~DataBaseText()
{
workerThread.quit();
workerThread.wait();
DataBaseText::~DataBaseText() {
workerThread.quit();
workerThread.wait();
}

//---------------

//from here on main worker. WARING not in main thread.

void DataBaseWorkerText::DbLookupFromAES(const QString &dirname, const QString &AEStext,int userdata,QObject *sender,const char * member)
{

QStringList values;

if(cache.maxCost()<300)cache.setMaxCost(300);

//serve cached entries
QStringList *pvalues=cache.object(AEStext);
if(pvalues)
{
QStringList values=*pvalues;
if(!values.size())
{
values.push_back("Not found");
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, true),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}

//open db
if(!db.isOpen())
{
//get a file that kind of matches, ignore case and add a bit of wildcards
QDir dir(dirname);
QStringList files=dir.entryList(QStringList()<<"basestation*.sqb",QDir::Files | QDir::Readable | QDir::NoDotAndDotDot | QDir::NoDot);
QFile file;
//if the user specified location doesn't contain the basestation file then
//fallback and try the application path
if(files.size())file.setFileName(dir.path()+"/"+files[0]);
if(!files.size()||!file.exists())
{
dir.setPath(QCoreApplication::applicationDirPath());
files=dir.entryList(QStringList()<<"basestation*.sqb",QDir::Files | QDir::Readable | QDir::NoDotAndDotDot | QDir::NoDot);
if(files.size())file.setFileName(dir.path()+"/"+files[0]);
}
if(!files.size()||!file.exists())
{
values.push_back("Database file basestation.sqb not found");
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}
//try and open the database
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(file.fileName());
if (!db.open())
{
values.push_back("Cant open SQL database");
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}
qDebug()<<"db opened ("<<db.databaseName()<<")";

}

//req from db
QSqlQuery query;
bool bStatus = false;
uint aes=AEStext.toUInt(&bStatus,16);
QString aes_as_hex_uppercase_and_6_places = QString("%1").arg(aes, 6, 16, QLatin1Char( '0' )).toUpper();//in case aes is less than 6 places
QString req = "SELECT * FROM Aircraft WHERE ModeS LIKE '"+aes_as_hex_uppercase_and_6_places+"';";

if(!query.exec(req))
{
values.push_back("Error: "+query.lastError().text());
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}

if(!query.next())
{
//not found
cache.insert(AEStext,new QStringList);
values.clear();values.push_back("Not found");
QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, false),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;
}

//fill in the local shema DataBaseTextUser::DataBaseSchema
QSqlRecord rec = query.record();
QMetaEnum en = QMetaEnum::fromType<DataBaseTextUser::DataBaseSchema>();
for(int k=0;k<en.keyCount();k++)
{
values.push_back(rec.value(en.key(k)).toString().trimmed());
}

cache.insert(AEStext,new QStringList(values));

QMetaObject::invokeMethod(sender,member, Qt::QueuedConnection,Q_ARG(bool, true),Q_ARG(int, userdata),Q_ARG(const QStringList&, values));
return;

}

95 changes: 35 additions & 60 deletions decode/databasetext.h
Original file line number Diff line number Diff line change
@@ -1,87 +1,62 @@
#ifndef DATABASETEXT_H
#define DATABASETEXT_H

#include <QObject>
#include <QThread>
#include <QFile>
#include <QTextStream>
#include <QCache>
#include <QDebug>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QFile>
#include <QMetaEnum>
#include <QObject>
#include <QTextStream>
#include <QThread>

#define DataBaseTextUser_MAX_PACKETS_IN_QUEUE 100

//Only DataBaseTextUser and DBase should be used directly
// Only DataBaseTextUser and DBase should be used directly

class DataBaseWorkerText : public QObject
{
Q_OBJECT
public:
public slots:
void DbLookupFromAES(const QString &dirname, const QString &AEStext,int userdata,QObject *sender,const char * member);
signals:
private:
QCache<QString, QStringList> cache;
QSqlDatabase db;
class DataBaseText : public QObject {
Q_OBJECT
QThread workerThread;

};

class DataBaseText : public QObject
{
Q_OBJECT
QThread workerThread;
public:
explicit DataBaseText(QObject *parent = 0);
~DataBaseText();
explicit DataBaseText(QObject *parent = 0);
~DataBaseText();
signals:
void asyncDbLookupFromAES(const QString &dirname, const QString &AEStext,int userdata,QObject *sender,const char * member);
void asyncDbLookupFromAES(const QString &dirname, const QString &AEStext,
int userdata, QObject *sender, const char *member);
public slots:
private slots:
};

extern DataBaseText *dbtext;

class DBase
{

};
class DataBaseTextUser : public QObject
{
Q_OBJECT
class DBase {};
class DataBaseTextUser : public QObject {
Q_OBJECT
public:

enum DataBaseSchema
{
ModeS,
ModeSCountry,
Registration,
Manufacturer,
ICAOTypeCode,
Type,
RegisteredOwners
};
Q_ENUM(DataBaseSchema)


DataBaseTextUser(QObject *parent = 0);
~DataBaseTextUser();
void clear();
DBase* getuserdata(int ref);
enum DataBaseSchema {
ModeS,
ModeSCountry,
Registration,
Manufacturer,
ICAOTypeCode,
Type,
RegisteredOwners
};
Q_ENUM(DataBaseSchema)

DataBaseTextUser(QObject *parent = 0);
~DataBaseTextUser();
void clear();
DBase *getuserdata(int ref);
public slots:
void request(const QString &dirname, const QString &AEStext,DBase* userdata);
void request(const QString &dirname, const QString &AEStext, DBase *userdata);
signals:
void result(bool ok, int ref, const QStringList &result);
void result(bool ok, int ref, const QStringList &result);

private:
QMap<int,DBase*> map;
int refcounter;
QMap<int, DBase *> map;
int refcounter;
private slots:
};




#endif // DATABASETEXT_H

0 comments on commit 0620d2c

Please sign in to comment.