File indexing completed on 2024-07-21 06:28:19

0001 /*
0002     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "indi/indidbus.h"
0010 #include "indicommon.h"
0011 #include "customdrivers.h"
0012 #include "ui_drivermanager.h"
0013 
0014 #include <QDialog>
0015 #include <QFrame>
0016 #include <QIcon>
0017 #include <QString>
0018 #include <QPointer>
0019 #include <QJsonArray>
0020 
0021 #include <lilxml.h>
0022 
0023 class QStringList;
0024 class QTreeWidgetItem;
0025 
0026 class DriverManager;
0027 class ServerManager;
0028 class ClientManager;
0029 class DriverInfo;
0030 
0031 class DriverManagerUI : public QFrame, public Ui::DriverManager
0032 {
0033         Q_OBJECT
0034 
0035     public:
0036         explicit DriverManagerUI(QWidget *parent = nullptr);
0037 
0038     public slots:
0039         void makePortEditable(QTreeWidgetItem *selectedItem, int column);
0040 
0041     public:
0042         QIcon runningPix;
0043         QIcon stopPix;
0044         QIcon connected;
0045         QIcon disconnected;
0046         QIcon localMode;
0047         QIcon serverMode;
0048 };
0049 
0050 /**
0051  * @brief DriverManager is the primary class to handle all operations related to starting and stopping INDI drivers.
0052  *
0053  * INDI drivers can be local or remote drivers. For remote hosts, driver information is not known and devices are built
0054  * as they arrive dynamically. The class parses INDI primary devices XML file (drivers.xml) and any 3rd party INDI Driver
0055  * XML file to build a tree of devices grouped by driver family type.
0056  *
0057  * When starting local drivers, DriverManager also establishes an INDI server with the requested drivers and then connect to
0058  * the local server to receive the devices dynamically.
0059  *
0060  * The class also handles INDI hosts which can be added in order to connect to a local or remote INDI server.
0061  *
0062  * @author Jasem Mutlaq
0063  */
0064 class DriverManager : public QDialog
0065 {
0066         Q_OBJECT
0067 
0068     public:
0069         static DriverManager *Instance();
0070         static void release();
0071 
0072         enum
0073         {
0074             LOCAL_NAME_COLUMN = 0,
0075             LOCAL_STATUS_COLUMN,
0076             LOCAL_MODE_COLUMN,
0077             LOCAL_VERSION_COLUMN,
0078             LOCAL_PORT_COLUMN
0079         };
0080         enum
0081         {
0082             HOST_STATUS_COLUMN = 0,
0083             HOST_NAME_COLUMN,
0084             HOST_PORT_COLUMN
0085         };
0086 
0087         bool readXMLDrivers();
0088         bool readINDIHosts();
0089         void processXMLDriver(const QString &driverName);
0090         bool buildDeviceGroup(XMLEle *root, char errmsg[]);
0091         bool buildDriverElement(XMLEle *root, QTreeWidgetItem *DGroup, DeviceFamily groupType, char errmsg[]);
0092 
0093         int getINDIPort(int customPort);
0094         bool isDeviceRunning(const QString &deviceLabel);
0095 
0096         void saveHosts();
0097 
0098         void processLocalTree(bool dState);
0099         void processRemoteTree(bool dState);
0100 
0101         QSharedPointer<DriverInfo> findDriverByName(const QString &name);
0102         QSharedPointer<DriverInfo> findDriverByLabel(const QString &label);
0103         QSharedPointer<DriverInfo> findDriverByExec(const QString &exec);
0104 
0105         ClientManager *getClientManager(const QSharedPointer<DriverInfo> &driver);
0106 
0107         const QList<QSharedPointer<DriverInfo>> &getDrivers() const
0108         {
0109             return driversList;
0110         }
0111         const QList<QVariantMap> &getCustomDrivers() const
0112         {
0113             return m_CustomDrivers->customDrivers();
0114         }
0115         QJsonArray getDriverList() const;
0116 
0117         const QStringList &getDriversStringList()
0118         {
0119             return driversStringList;
0120         }
0121 
0122         /**
0123          * @brief getUniqueHosts Given a list of DriverInfos, extract all the host:port information from all the drivers.
0124          * and then consolidate each groups of drivers that belong to the same server & port to a specific list
0125          * e.g. If we have driver1 (localhost:7624), driver2(192.168.1.90:7624), driver3(localhost:7624) then this would create
0126          * two lists. First list contains [driver1,driver3] and second list contains [driver2] making each list _unique_ in terms of host params.
0127          * @param dList list of driver to examine
0128          * @param uHosts List of unique hosts, each with a group of drivers that belong to it.
0129          */
0130         void getUniqueHosts(const QList<QSharedPointer<DriverInfo>> &dList, QList<QList<QSharedPointer<DriverInfo>>> &uHosts);
0131 
0132         void addDriver(const QSharedPointer<DriverInfo> &driver)
0133         {
0134             driversList.append(driver);
0135         }
0136         void removeDriver(const QSharedPointer<DriverInfo> &driver)
0137         {
0138             driversList.removeOne(driver);
0139         }
0140 
0141         void startDevices(const QList<QSharedPointer<DriverInfo> > &dList);
0142         void stopDevices(const QList<QSharedPointer<DriverInfo>> &dList);
0143         void stopAllDevices()
0144         {
0145             stopDevices(driversList);
0146         }
0147         bool restartDriver(const QSharedPointer<DriverInfo> &driver);
0148 
0149         void connectRemoteHost(const QSharedPointer<DriverInfo> &driver);
0150         bool disconnectRemoteHost(const QSharedPointer<DriverInfo> &driver);
0151 
0152         QString getUniqueDeviceLabel(const QString &label);
0153 
0154         void startClientManager(const QList<QSharedPointer<DriverInfo>> &qdv, const QString &host, int port);
0155         void startLocalDrivers(ServerManager *serverManager);
0156         void processDriverStartup(const QSharedPointer<DriverInfo> &driver);
0157         void processDriverFailure(const QSharedPointer<DriverInfo> &driver, const QString &message);
0158 
0159         void disconnectClients();
0160         void clearServers();
0161 
0162     private:
0163         DriverManager(QWidget *parent);
0164         ~DriverManager() override;
0165 
0166         bool checkDriverAvailability(const QString &driver);
0167 
0168         static DriverManager *_DriverManager;
0169         static INDIDBus *_INDIDBus;
0170 
0171         ServerMode connectionMode { SERVER_CLIENT };
0172         QTreeWidgetItem *lastGroup { nullptr };
0173         int currentPort;
0174         //DriverInfo::XMLSource xmlSource;
0175         DriverSource driverSource;
0176         DriverManagerUI *ui { nullptr };
0177         QList<QSharedPointer<DriverInfo>> driversList;
0178         QList<ServerManager *> servers;
0179         QList<ClientManager *> clients;
0180         QStringList driversStringList;
0181         QPointer<CustomDrivers> m_CustomDrivers;
0182 
0183     public slots:
0184         void resizeDeviceColumn();
0185         void updateLocalTab();
0186         void updateClientTab();
0187 
0188         void updateMenuActions();
0189 
0190         void addINDIHost();
0191         void modifyINDIHost();
0192         void removeINDIHost();
0193         void activateRunService();
0194         void activateStopService();
0195         void activateHostConnection();
0196         void activateHostDisconnection();
0197 
0198         void updateCustomDrivers();
0199 
0200         void setClientStarted();
0201         void setClientFailed(const QString &message);
0202         void setClientTerminated(const QString &message);
0203 
0204         void setServerStarted();
0205         void setServerFailed(const QString &message);
0206         void setServerTerminated(const QString &message);
0207 
0208         void processDeviceStatus(const QSharedPointer<DriverInfo> &driver);
0209 
0210         void showCustomDrivers()
0211         {
0212             m_CustomDrivers->show();
0213         }
0214 
0215     signals:
0216 
0217         // Server Signals
0218 
0219         // Server started successfully
0220         void serverStarted(const QString &host, int port);
0221         // Server failed to start.
0222         void serverFailed(const QString &host, int port, const QString &message);
0223         // Running server was abruptly terminated.
0224         void serverTerminated(const QString &host, int port, const QString &message);
0225 
0226         // Client Signals
0227         // Client connected to server successfully.
0228         void clientStarted(const QString &host, int port);
0229         // Client failed to connect to server.
0230         void clientFailed(const QString &host, int port, const QString &message);
0231         // Running server lost connection to server.
0232         void clientTerminated(const QString &host, int port, const QString &message);
0233 
0234         // Driver Signals
0235         void driverStarted(const QSharedPointer<DriverInfo> &driver);
0236         void driverFailed(const QSharedPointer<DriverInfo> &driver, const QString &message);
0237         void driverStopped(const QSharedPointer<DriverInfo> &driver);
0238         void driverRestarted(const QSharedPointer<DriverInfo> &driver);
0239 };