Commit ed5f76d6 authored by Jasem Mutlaq's avatar Jasem Mutlaq

Adding driver profiles feature to Ekos in order to support multiple local and...

Adding driver profiles feature to Ekos in order to support multiple local and remote observatory profiles
parent 2261ba1d
......@@ -92,6 +92,7 @@ if (CFITSIO_FOUND)
ekos/focus.ui
ekos/guide.ui
ekos/mount.ui
ekos/profileeditor.ui
ekos/guide/guider.ui
ekos/guide/rcalibration.ui
)
......@@ -114,6 +115,8 @@ if (CFITSIO_FOUND)
ekos/astrometryparser.cpp
ekos/offlineastrometryparser.cpp
ekos/onlineastrometryparser.cpp
ekos/profileeditor.cpp
ekos/profileinfo.cpp
ekos/opsekos.cpp
ekos/QProgressIndicator.cpp
ekos/guide/common.cpp
......
......@@ -63,6 +63,8 @@ bool KSUserDB::Initialize() {
QSqlRecord record = version.record(0);
qDebug() << " Verion string is " << record.value("Version").toString();
version.clear();
// If prior to 2.4.0 upgrade database for horizon table
if (record.value("Version").toString() < "2.4.0")
{
QSqlQuery query(userdb_);
......@@ -74,6 +76,40 @@ bool KSUserDB::Initialize() {
if (!query.exec("CREATE TABLE IF NOT EXISTS horizons (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, label TEXT NOT NULL, enabled INTEGER NOT NULL)"))
qDebug() << query.lastError();
}
// If prior to 2.6.0 upgrade database for profiles tables
if (record.value("Version").toString() < "2.6.0")
{
QSqlQuery query(userdb_);
QString versionQuery = QString("UPDATE Version SET Version='%1'").arg(KSTARS_VERSION);
if (!query.exec(versionQuery))
qDebug() << query.lastError();
// Profiles
if (!query.exec("CREATE TABLE IF NOT EXISTS profile (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, host TEXT, port INTEGER)"))
qDebug() << query.lastError();
// Drivers
if (!query.exec("CREATE TABLE IF NOT EXISTS driver (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, label TEXT NOT NULL, role TEXT NOT NULL, profile INTEGER NOT NULL, FOREIGN KEY(profile) REFERENCES profile(id))"))
qDebug() << query.lastError();
// Custom Drivers
//if (!query.exec("CREATE TABLE IF NOT EXISTS custom_driver (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, drivers TEXT NOT NULL, profile INTEGER NOT NULL, FOREIGN KEY(profile) REFERENCES profile(id))"))
//qDebug() << query.lastError();
// Add sample profile
if (!query.exec("INSERT INTO profile (name) VALUES ('Simulators')"))
qDebug() << query.lastError();
// Add sample profile drivers
if (!query.exec("INSERT INTO driver (label, role, profile) VALUES ('Telescope Simulator', 'Mount', 1)"))
qDebug() << query.lastError();
if (!query.exec("INSERT INTO driver (label, role, profile) VALUES ('CCD Simulator', 'CCD', 1)"))
qDebug() << query.lastError();
if (!query.exec("INSERT INTO driver (label, role, profile) VALUES ('Focuser Simulator', 'Focuser', 1)"))
qDebug() << query.lastError();
}
}
}
userdb_.close();
......@@ -93,9 +129,9 @@ bool KSUserDB::FirstRun() {
if (!RebuildDB())
return false;
ImportFlags();
/*ImportFlags();
ImportUsers();
ImportEquipment();
ImportEquipment();*/
return true;
}
......@@ -185,6 +221,14 @@ bool KSUserDB::RebuildDB() {
"label TEXT NOT NULL,"
"enabled INTEGER NOT NULL)");
tables.append("CREATE TABLE profile (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, host TEXT, port INTEGER)");
tables.append("CREATE TABLE driver (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, label TEXT NOT NULL, role TEXT NOT NULL, profile INTEGER NOT NULL, FOREIGN KEY(profile) REFERENCES profile(id))");
//tables.append("CREATE TABLE custom_driver (id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, drivers TEXT NOT NULL, profile INTEGER NOT NULL, FOREIGN KEY(profile) REFERENCES profile(id))");
tables.append("INSERT INTO profile (name) VALUES ('Simulators')");
tables.append("INSERT INTO driver (label, role, profile) VALUES ('Telescope Simulator', 'Mount', 1)");
tables.append("INSERT INTO driver (label, role, profile) VALUES ('CCD Simulator', 'CCD', 1)");
tables.append("INSERT INTO driver (label, role, profile) VALUES ('Focuser Simulator', 'Focuser', 1)");
for (int i = 0; i < tables.count(); ++i) {
QSqlQuery query(userdb_);
if (!query.exec(tables[i])) {
......@@ -660,6 +704,7 @@ void KSUserDB::GetAllFilters(QList<OAL::Filter *> &filter_list) {
return;
}
#if 0
bool KSUserDB::ImportFlags() {
QString flagfilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "flags.dat";
QFile flagsfile(flagfilename);
......@@ -790,6 +835,7 @@ bool KSUserDB::ImportEquipment() {
equipfile.close();
return true;
}
#endif
void KSUserDB::readScopes() {
while( ! reader_->atEnd() ) {
......@@ -1068,3 +1114,163 @@ void KSUserDB::AddHorizon(ArtificialHorizonEntity *horizon)
userdb_.close();
}
int KSUserDB::AddProfile(const QString &name)
{
userdb_.open();
int id=-1;
QSqlQuery query(userdb_);
bool rc = query.exec(QString("INSERT INTO profile (name) VALUES('%1')").arg(name));
if (rc == false)
qDebug() << query.lastQuery() << query.lastError().text();
else
id = query.lastInsertId().toInt();
userdb_.close();
return id;
}
bool KSUserDB::DeleteProfile(ProfileInfo *pi)
{
userdb_.open();
QSqlQuery query(userdb_);
bool rc;
rc = query.exec("DELETE FROM profile WHERE id=" + QString::number(pi->id));
if (rc == false)
qDebug() << query.lastQuery() << query.lastError().text();
userdb_.close();
return rc;
}
void KSUserDB::SaveProfile(ProfileInfo *pi)
{
// Remove all drivers
DeleteProfileDrivers(pi);
userdb_.open();
QSqlQuery query(userdb_);
// If LOCAL mode
if (pi->host.isEmpty())
{
if (!query.exec(QString("UPDATE profile SET name='%1',host=null,port=null WHERE id=%2").arg(pi->name).arg(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();
}
// if REMOTE mode
else
{
if (!query.exec(QString("UPDATE profile SET name='%1',host='%2',port=%3 WHERE id=%4").arg(pi->name).arg(pi->host).arg((pi->port)).arg(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();
}
QMapIterator<QString, QString> i(pi->drivers);
while (i.hasNext())
{
i.next();
if (!query.exec(QString("INSERT INTO driver (label, role, profile) VALUES('%1','%2',%3)").arg(i.value()).arg(i.key()).arg(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();
}
/*if (pi->customDrivers.isEmpty() == false && !query.exec(QString("INSERT INTO custom_driver (drivers, profile) VALUES('%1',%2)").arg(pi->customDrivers).arg(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();*/
userdb_.close();
}
QList<ProfileInfo *> KSUserDB::GetAllProfiles()
{
QList<ProfileInfo *> profiles;
userdb_.open();
QSqlTableModel profile(0, userdb_);
profile.setTable("profile");
profile.select();
for (int i =0; i < profile.rowCount(); ++i)
{
QSqlRecord record = profile.record(i);
int id = record.value("id").toInt();
QString name = record.value("name").toString();
ProfileInfo *pi = new ProfileInfo(id, name);
// Add host and port
pi->host = record.value("host").toString();
pi->port = record.value("port").toInt();
GetProfileDrivers(pi);
//GetProfileCustomDrivers(pi);
profiles.append(pi);
}
profile.clear();
userdb_.close();
return profiles;
}
void KSUserDB::GetProfileDrivers(ProfileInfo* pi)
{
userdb_.open();
QSqlTableModel driver(0, userdb_);
driver.setTable("driver");
driver.setFilter("profile=" + QString::number(pi->id));
if (driver.select() == false)
qDebug() << "driver select error: " << driver.query().lastQuery() << driver.lastError().text();
for (int i =0; i < driver.rowCount(); ++i)
{
QSqlRecord record = driver.record(i);
QString label = record.value("label").toString();
QString role = record.value("role").toString();
pi->drivers[role] = label;
}
driver.clear();
userdb_.close();
}
/*void KSUserDB::GetProfileCustomDrivers(ProfileInfo* pi)
{
userdb_.open();
QSqlTableModel custom_driver(0, userdb_);
custom_driver.setTable("driver");
custom_driver.setFilter("profile=" + QString::number(pi->id));
if (custom_driver.select() == false)
qDebug() << "custom driver select error: " << custom_driver.query().lastQuery() << custom_driver.lastError().text();
QSqlRecord record = custom_driver.record(0);
pi->customDrivers = record.value("drivers").toString();
custom_driver.clear();
userdb_.close();
}*/
void KSUserDB::DeleteProfileDrivers(ProfileInfo* pi)
{
userdb_.open();
QSqlQuery query(userdb_);
/*if (!query.exec("DELETE FROM custom_driver WHERE profile=" + QString::number(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();*/
if (!query.exec("DELETE FROM driver WHERE profile=" + QString::number(pi->id)))
qDebug() << query.lastQuery() << query.lastError().text();
userdb_.close();
}
......@@ -34,6 +34,7 @@
#include <QXmlStreamReader>
#include "skyobjects/skyobject.h"
#include "oal/oal.h"
#include "ekos/profileinfo.h"
class LineList;
class ArtificialHorizonEntity;
......@@ -55,6 +56,23 @@ class KSUserDB {
QSqlDatabase GetDatabase();
/************************************************************************
********************************* Drivers ******************************
************************************************************************/
int AddProfile(const QString &name);
bool DeleteProfile(ProfileInfo *pi);
void SaveProfile(ProfileInfo *pi);
/**
* @brief GetAllProfiles Return all profiles in a QList
* @return QMap with the keys as profile names and values are profile ids.
*/
//QMap<int, QStringList> GetAllProfiles();
QList<ProfileInfo *> GetAllProfiles();
/************************************************************************
******************************* Observers ******************************
************************************************************************/
......@@ -264,6 +282,8 @@ class KSUserDB {
* @return bool
**/
bool FirstRun();
#if 0
/**
* @brief Imports flags data from previous format
*
......@@ -282,6 +302,8 @@ class KSUserDB {
* @return bool
**/
bool ImportEquipment();
#endif
/**
* @brief Helper functions
*
......@@ -295,6 +317,12 @@ class KSUserDB {
void readLens();
void readFilters();
void readFilter();
void DeleteProfileDrivers(ProfileInfo *pi);
void GetProfileDrivers(ProfileInfo *pi);
//void GetProfileCustomDrivers(ProfileInfo *pi);
/**
* @brief Linked to the user database _once_.
**/
......
......@@ -537,13 +537,19 @@ QString constGenetiveToAbbrev( const QString &genetive_ ) {
void Logging::UseFile(const QString &filename)
{
_filename = filename;
// Clear file contents
QFile file(filename);
file.open(QFile::WriteOnly);
file.close();
qInstallMessageHandler(File);
}
void Logging::File(QtMsgType type, const QMessageLogContext &, const QString &msg)
{
QFile file(_filename);
if(file.open(QFile::WriteOnly | QIODevice::Text))
if(file.open(QFile::Append | QIODevice::Text))
{
QTextStream stream(&file);
Write(stream, type, msg);
......
This diff is collapsed.
......@@ -30,6 +30,7 @@
#include <QtDBus/QtDBus>
class DriverInfo;
class ProfileInfo;
class KPageWidgetItem;
/**
......@@ -62,7 +63,7 @@ public:
typedef enum { STATUS_IDLE, STATUS_PENDING, STATUS_SUCCESS, STATUS_ERROR } CommunicationStatus;
void appendLogText(const QString &);
void refreshRemoteDrivers();
//void refreshRemoteDrivers();
void setOptionsWidget(KPageWidgetItem *ops) { ekosOption = ops; }
void addObjectToScheduler(SkyObject *object);
......@@ -83,7 +84,9 @@ public:
* @param isLocal if true, it will establish INDI server locally, otherwise it will connect to a remote INDI server as defined in the Ekos options or by the user.
* /note This function must be called before all functions in Ekos DBUS Interface.
*/
Q_SCRIPTABLE Q_NOREPLY void setConnectionMode(bool isLocal);
//Q_SCRIPTABLE Q_NOREPLY void setConnectionMode(bool isLocal);
Q_SCRIPTABLE bool setProfile(const QString &profileName);
/** DBUS interface function.
* @retrun INDI connection status (0 Idle, 1 Pending, 2 Connected, 3 Error)
......@@ -107,6 +110,7 @@ public:
*/
Q_SCRIPTABLE bool stop();
#if 0
/** DBUS interface function.
* Sets the telescope driver name. If connection mode is local, it is selected from the local drivers combo box. Otherwise, it is set as the remote telescope driver.
* @param telescopeName telescope driver name. For remote devices, the name has to be exactly as the name defined by the driver on startup.
......@@ -161,7 +165,8 @@ public:
* @param index 1 for Aux 1, 2 for Aux 2, 3 for Aux 3
* @param auxiliaryName auxiliary driver name. For remote devices, the name has to be exactly as the name defined by the driver on startup.
*/
Q_SCRIPTABLE Q_NOREPLY void setAuxiliary(int index, const QString & auxiliaryName);
Q_SCRIPTABLE Q_NOREPLY void setAuxiliary(int index, const QString & auxiliaryName);
#endif
protected:
void closeEvent(QCloseEvent *);
......@@ -190,7 +195,7 @@ public slots:
void processNewNumber(INumberVectorProperty *nvp);
void processNewText(ITextVectorProperty *tvp);
protected slots:
private slots:
void updateLog();
void clearLog();
......@@ -202,13 +207,9 @@ protected slots:
void deviceConnected();
void deviceDisconnected();
void processINDIModeChange();
//void processINDIModeChange();
void checkINDITimeout();
void toggleINDIPanel();
void toggleFITSViewer();
void checkFITSViewerState();
void setTelescope(ISD::GDInterface *);
void setCCD(ISD::GDInterface *);
void setFilter(ISD::GDInterface *);
......@@ -217,7 +218,12 @@ protected slots:
void setWeather(ISD::GDInterface *);
void setDustCap(ISD::GDInterface *);
void setLightBox(ISD::GDInterface *);
void setST4(ISD::ST4 *);
void setST4(ISD::ST4 *);
void addProfile();
void editProfile();
void deleteProfile();
void saveDefaultProfile(const QString& name);
private:
......@@ -232,11 +238,13 @@ protected slots:
void initWeather();
void initDustCap();
void initLocalDrivers();
void initRemoteDrivers();
//void initLocalDrivers();
//void initRemoteDrivers();
void loadDrivers();
void loadProfiles();
void saveLocalDrivers();
void saveRemoteDrivers();
//void saveLocalDrivers();
//void saveRemoteDrivers();
void processLocalDevice(ISD::GDInterface*);
void processRemoteDevice(ISD::GDInterface*);
......@@ -250,8 +258,8 @@ protected slots:
bool remoteCCDRegistered;
bool remoteGuideRegistered;
ISD::GDInterface *scope, *ccd, *guider, *focuser, *filter, *aux1, *aux2, *aux3, *aux4, *dome, *ao, *weather, *dustCap, *lightBox;
DriverInfo *scope_di, *ccd_di, *guider_di, *filter_di, *focuser_di, *aux1_di, *aux2_di, *aux3_di,*aux4_di, *ao_di, *dome_di, *weather_di, *remote_indi;
ISD::GDInterface *mount, *ccd, *guider, *focuser, *filter, *aux1, *aux2, *aux3, *aux4, *dome, *ao, *weather, *dustCap, *lightBox;
DriverInfo *mount_di, *ccd_di, *guider_di, *filter_di, *focuser_di, *aux1_di, *aux2_di, *aux3_di,*aux4_di, *ao_di, *dome_di, *weather_di, *remote_indi;
Ekos::Capture *captureProcess;
Ekos::Focus *focusProcess;
......@@ -269,12 +277,18 @@ protected slots:
int nDevices, nRemoteDevices;
QAtomicInt nConnectedDevices;
QList<DriverInfo *> managedDevices;
QList<DriverInfo *> managedDevices, customDrivers;
QHash<QString, DriverInfo *> driversList;
QStringList logText;
KPageWidgetItem *ekosOption;
CommunicationStatus ekosStartingStatus, indiConnectionStatus;
QStandardItemModel *profileModel;
QList<ProfileInfo *> profiles;
ProfileInfo * getCurrentProfile();
};
......
This diff is collapsed.
......@@ -49,7 +49,7 @@ void OpsEkos::slotApply()
if (ekosManager)
{
ekosManager->refreshRemoteDrivers();
//ekosManager->refreshRemoteDrivers();
Ekos::Guide *guideModule = ekosManager->guideModule();
......
......@@ -23,60 +23,6 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Remote Server</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Host:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="kcfg_remoteHost">
<property name="text">
<string notr="true">localhost</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="kcfg_remotePort">
<property name="text">
<string>7624</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
......@@ -114,168 +60,11 @@
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Optionally&lt;/span&gt; set remote device names if they do not exist in Ekos.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Remote Devices Names</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Mount</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="kcfg_remoteScopeName"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>CCD</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="kcfg_remoteCCDName">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Aux #1</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLineEdit" name="kcfg_remoteAux1Name"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Guider</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="kcfg_remoteGuiderName"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_19">
<property name="text">
<string>AO</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="kcfg_remoteAOName">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Aux #2</string>