Warning, file /education/kstars/kstars/ekos/manager.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 #ifdef USE_QT5_INDI
0010 #include <baseclientqt.h>
0011 #else
0012 #include <baseclient.h>
0013 #endif
0014 
0015 #include "ui_manager.h"
0016 
0017 #include "ekos.h"
0018 #include "fitsviewer/summaryfitsview.h"
0019 #include "indi/indistd.h"
0020 #include "auxiliary/portselector.h"
0021 #include "ksnotification.h"
0022 #include "auxiliary/opslogs.h"
0023 
0024 #include <QDialog>
0025 #include <QHash>
0026 #include <QtDBus/QtDBus>
0027 
0028 #include <memory>
0029 
0030 //! Generic record interfaces and implementations.
0031 namespace EkosLive
0032 {
0033 class Client;
0034 class Message;
0035 class Media;
0036 }
0037 
0038 class DriverInfo;
0039 class ProfileInfo;
0040 class KPageWidgetItem;
0041 class OpsEkos;
0042 
0043 /**
0044  * @class Manager
0045  * @short Primary class to handle all Ekos modules.
0046  * The Ekos Manager class manages startup and shutdown of INDI devices and registeration of devices within Ekos Modules. Ekos module consist of \ref Ekos::Mount, \ref Ekos::Capture, \ref Ekos::Focus, \ref Ekos::Guide, and \ref Ekos::Align modules.
0047  * \defgroup EkosDBusInterface "Ekos DBus Interface" provides high level functions to control devices and Ekos modules for a total robotic operation:
0048  * <ul>
0049  * <li>\ref CaptureDBusInterface "Capture Module DBus Interface"</li>
0050  * <li>\ref FocusDBusInterface "Focus Module DBus Interface"</li>
0051  * <li>\ref MountDBusInterface "Mount Module DBus Interface"</li>
0052  * <li>\ref GuideDBusInterface "Guide Module DBus Interface"</li>
0053  * <li>\ref AlignDBusInterface "Align Module DBus Interface"</li>
0054  * <li>\ref WeatherDBusInterface "Weather DBus Interface"</li>
0055  * <li>\ref DustCapDBusInterface "Dust Cap DBus Interface"</li>
0056  * </ul>
0057  *  For low level access to INDI devices, the \ref INDIDBusInterface "INDI Dbus Interface" provides complete access to INDI devices and properties.
0058  *  Ekos Manager provides a summary of operations progress in the <i>Summary</i> section of the <i>Setup</i> tab.
0059  *
0060  * @author Jasem Mutlaq
0061  * @version 1.8
0062  */
0063 namespace Ekos
0064 {
0065 
0066 class Analyze;
0067 class Capture;
0068 class Scheduler;
0069 class Focus;
0070 class Align;
0071 class Guide;
0072 class Mount;
0073 class Observatory;
0074 
0075 class Manager : public QDialog, public Ui::Manager
0076 {
0077         Q_OBJECT
0078         Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.Ekos")
0079 
0080         Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus indiStatus READ indiStatus NOTIFY indiStatusChanged)
0081         Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus ekosStatus READ ekosStatus NOTIFY ekosStatusChanged)
0082         Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus settleStatus READ settleStatus NOTIFY settleStatusChanged)
0083         Q_SCRIPTABLE Q_PROPERTY(bool ekosLiveStatus READ ekosLiveStatus NOTIFY ekosLiveStatusChanged)
0084         Q_SCRIPTABLE Q_PROPERTY(QStringList logText READ logText NOTIFY newLog)
0085 
0086         enum class EkosModule
0087         {
0088             Setup,
0089             Scheduler,
0090             Analyze,
0091             Capture,
0092             Focus,
0093             Mount,
0094             Align,
0095             Guide,
0096             Observatory,
0097         };
0098     public:
0099         static Manager *Instance();
0100         static void release();
0101 
0102         // No OP
0103         void initialize() {}
0104 
0105         void appendLogText(const QString &);
0106         void setOptionsWidget(KPageWidgetItem *ops, OpsEkos *opsEkosPtr)
0107         {
0108             ekosOptionsWidget = ops;
0109             opsEkos = opsEkosPtr;
0110         }
0111         void addObjectToScheduler(SkyObject *object);
0112 
0113         Scheduler *schedulerModule()
0114         {
0115             return schedulerProcess.get();
0116         }
0117         Guide *guideModule()
0118         {
0119             return guideProcess.get();
0120         }
0121         Align *alignModule()
0122         {
0123             return alignProcess.get();
0124         }
0125         Mount *mountModule()
0126         {
0127             return mountProcess.get();
0128         }
0129         Focus *focusModule()
0130         {
0131             return focusProcess.get();
0132         }
0133         Capture *captureModule()
0134         {
0135             return captureProcess.get();
0136         }
0137         FITSView *getSummaryPreview()
0138         {
0139             return m_SummaryView.get();
0140         }
0141 
0142         // Filter Manager
0143         void createFilterManager(ISD::FilterWheel *device);
0144         bool getFilterManager(const QString &name, QSharedPointer<FilterManager> &fm);
0145 
0146         QString getCurrentJobName();
0147         void announceEvent(const QString &message, KSNotification::EventSource source, KSNotification::EventType event);
0148 
0149         /**
0150          * @brief activateModule Switch tab to specific module name (i.e. CCD) and raise Ekos screen to focus.
0151          * @param name module name CCD, Guide, Focus, Mount, Scheduler, or Observatory.
0152          * @param popup if True, show Ekos Manager window in the foreground.
0153          */
0154         void activateModule(const QString &name, bool popup = false);
0155 
0156         /**
0157          * @brief addProfile Add a new profile to the database.
0158          * @param profileInfo Collection of profile parameters to include the following:
0159          * 1. name: Profile name
0160          * 2. auto_connect: True of False for Autoconnect?
0161          * 3. Mode: "local" or "remote"
0162          * 4. remote_host: Optional. remote host (default localhost)
0163          * 5. remote_port: Optional. remote port (default 7624)
0164          * 6. guiding: 0 for "Internal", 1 for "PHD2", or 2 for "LinGuider"
0165          * 7. remote_guiding_host: Optional. remote host for guider application (default localhost)
0166          * 8. remote_guide_port: Optional. remote port for guider application.
0167          * 9. use_web_manager: True or False?
0168          * 10. web_manager_port. Optional. INDI Web Manager port (default 8624)
0169          * 12. primary_scope: ID of primary scope to use. This is the ID from OAL::Scope list in the database.
0170          * 13. guide_scope: ID of guide scope to use. This is the ID from OAL::Scope list in the database.
0171          * 14. mount: Mount driver label (default --).
0172          * 15. ccd: CCD driver label (default --).
0173          * 16. guider: Guider driver label (default --).
0174          * 17. focuser: Focuser driver label (default --).
0175          * 18. filter: Filter Wheel driver label (default --).
0176          * 19. ao: Adaptive Optics driver label (default --).
0177          * 20. dome: Dome driver label (default --).
0178          * 21. Weather: Weather station driver label (default --).
0179          * 22. aux1: aux1 driver label (default --).
0180          * 23. aux2: aux2 driver label (default --).
0181          * 24. aux3: aux3 driver label (default --).
0182          * 25. aux4: aux4 driver label (default --).
0183          */
0184         void addNamedProfile(const QJsonObject &profileInfo);
0185 
0186         /** Same as above, except it edits an existing named profile */
0187         void editNamedProfile(const QJsonObject &profileInfo);
0188 
0189         /**
0190          * @brief deleteProfile Delete existing equipment profile
0191          * @param name Name of profile
0192          * @warning Ekos must be stopped for this to work. It will fail if Ekos is online.
0193          */
0194         void deleteNamedProfile(const QString &name);
0195 
0196         /**
0197          * @brief getProfile Get a single profile information.
0198          * @param name Profile name
0199          * @return A JSon object with the detail profile info as described in addProfile function.
0200          */
0201         QJsonObject getNamedProfile(const QString &name);
0202 
0203         /**
0204          * DBus commands to manage equipment profiles.
0205          */
0206 
0207         /*@{*/
0208 
0209         /**
0210          * DBUS interface function.
0211          * set Current device profile.
0212          * @param profileName Profile name
0213          * @return True if profile is set, false if not found.
0214          */
0215         Q_SCRIPTABLE bool setProfile(const QString &profileName);
0216 
0217         /**
0218          * DBUS interface function
0219          * @brief getProfiles Return a list of all device profiles
0220          * @return List of device profiles
0221          */
0222         Q_SCRIPTABLE QStringList getProfiles();
0223 
0224         /** @}*/
0225 
0226 
0227         /**
0228          * Manager interface provides advanced scripting capabilities to establish and shutdown Ekos services.
0229          */
0230 
0231         /*@{*/
0232 
0233         /**
0234          * DBUS interface function.
0235          * @return INDI connection status (0 Idle, 1 Pending, 2 Connected, 3 Error)
0236          * @deprecated
0237          */
0238         Q_SCRIPTABLE unsigned int getINDIConnectionStatus()
0239         {
0240             return m_indiStatus;
0241         }
0242 
0243         Q_SCRIPTABLE Ekos::CommunicationStatus indiStatus()
0244         {
0245             return m_indiStatus;
0246         }
0247 
0248         /**
0249          * DBUS interface function.
0250          * @return Ekos starting status (0 Idle, 1 Pending, 2 Started, 3 Error)
0251          * @deprecated
0252          */
0253         Q_SCRIPTABLE unsigned int getEkosStartingStatus()
0254         {
0255             return m_ekosStatus;
0256         }
0257 
0258         Q_SCRIPTABLE Ekos::CommunicationStatus ekosStatus()
0259         {
0260             return m_ekosStatus;
0261         }
0262 
0263         /**
0264          * DBUS interface function.
0265          * @return Settle status (0 Idle, 1 Pending, 2 Started, 3 Error)
0266          */
0267         Q_SCRIPTABLE Ekos::CommunicationStatus settleStatus()
0268         {
0269             return m_settleStatus;
0270         }
0271 
0272         /**
0273          * DBUS interface function. Toggle Ekos logging.
0274          * @param name Name of logging to toggle. Available options are:
0275          * ** VERBOSE
0276          * ** INDI
0277          * ** FITS
0278          * ** CAPTURE
0279          * ** FOCUS
0280          * ** GUIDE
0281          * ** ALIGNMENT
0282          * ** MOUNT
0283          * ** SCHEDULER
0284          * ** OBSERVATORY
0285          * @param enabled True to enable, false otherwise.
0286          */
0287         Q_SCRIPTABLE Q_NOREPLY void setEkosLoggingEnabled(const QString &name, bool enabled);
0288 
0289         /**
0290          * DBUS interface function.
0291          * If connection mode is local, the function first establishes an INDI server with all the specified drivers in Ekos options or as set by the user. For remote connection,
0292          * it establishes connection to the remote INDI server.
0293          * @return Returns true if server started successful (local mode) or connection to remote server is successful (remote mode).
0294          */
0295         Q_SCRIPTABLE void start();
0296 
0297         /**
0298          * DBUS interface function.
0299          * If connection mode is local, the function terminates the local INDI server and drivers. For remote, it disconnects from the remote INDI server.
0300          */
0301         Q_SCRIPTABLE void stop();
0302 
0303         Q_SCRIPTABLE QStringList logText()
0304         {
0305             return m_LogText;
0306         }
0307 
0308         Q_SCRIPTABLE bool ekosLiveStatus();
0309 
0310         /**
0311          * DBUS interface function.
0312          * @param enabled Connect to EkosLive if true, otherwise disconnect.
0313         */
0314         Q_SCRIPTABLE void setEkosLiveConnected(bool enabled);
0315 
0316         /**
0317          * @brief setEkosLiveConfig Set EkosLive settings
0318          * @param onlineService If true, connect to EkosLive Online Service. Otherwise, EkosLive offline service.
0319          * @param rememberCredentials Remember username and password for next session.
0320          * @param autoConnect If true, it will automatically connect to EkosLive service.
0321          */
0322         Q_SCRIPTABLE void setEkosLiveConfig(bool onlineService, bool rememberCredentials, bool autoConnect);
0323 
0324         /**
0325          * @brief setEkosLiveUser Save EkosLive username and password
0326          * @param username User name
0327          * @param password Password
0328          */
0329         Q_SCRIPTABLE void setEkosLiveUser(const QString &username, const QString &password);
0330 
0331         /**
0332          * @brief acceptPortSelection Accept current port selection settings in the Selector Dialog
0333          */
0334         Q_SCRIPTABLE void acceptPortSelection();
0335 
0336     signals:
0337         // Have to use full Ekos::CommunicationStatus for DBus signal to work
0338         void ekosStatusChanged(Ekos::CommunicationStatus status);
0339         void indiStatusChanged(Ekos::CommunicationStatus status);
0340         void settleStatusChanged(Ekos::CommunicationStatus status);
0341         void ekosLiveStatusChanged(bool status);
0342 
0343         void newLog(const QString &text);
0344         void newModule(const QString &name);
0345         void newDevice(const QString &name, int interface);
0346 
0347     protected:
0348         void closeEvent(QCloseEvent *event) override;
0349         void hideEvent(QHideEvent *) override;
0350         void showEvent(QShowEvent *) override;
0351         void resizeEvent(QResizeEvent *) override;
0352 
0353     public slots:
0354 
0355         /**
0356          * DBUS interface function.
0357          * Connects all the INDI devices started by Ekos.
0358          */
0359         Q_SCRIPTABLE Q_NOREPLY void connectDevices();
0360 
0361         /**
0362          * DBUS interface function.
0363          * Disconnects all the INDI devices started by Ekos.
0364          */
0365         Q_SCRIPTABLE Q_NOREPLY void disconnectDevices();
0366 
0367         /** @}*/
0368 
0369         void processINDI();
0370         void cleanDevices(bool stopDrivers = true);
0371 
0372         void processNewDevice(const QSharedPointer<ISD::GenericDevice> &device);
0373 
0374         void processNewProperty(INDI::Property);
0375         void processUpdateProperty(INDI::Property);
0376         void processDeleteProperty(INDI::Property);
0377 
0378         void setDeviceReady();
0379 
0380         void restartDriver(const QString &deviceName);
0381 
0382     private slots:
0383 
0384         void changeAlwaysOnTop(Qt::ApplicationState state);
0385 
0386         void showEkosOptions();
0387 
0388         void updateLog();
0389         void clearLog();
0390 
0391         void processTabChange();
0392 
0393         void setServerStarted(const QString &host, int port);
0394         void setServerFailed(const QString &host, int port, const QString &message);
0395         //void setServerTerminated(const QString &host, int port, const QString &message);
0396 
0397         void setClientStarted(const QString &host, int port);
0398         void setClientFailed(const QString &host, int port, const QString &message);
0399         void setClientTerminated(const QString &host, int port, const QString &message);
0400 
0401         void removeDevice(const QSharedPointer<ISD::GenericDevice> &device);
0402 
0403         void deviceConnected();
0404         void deviceDisconnected();
0405 
0406         //void processINDIModeChange();
0407         void checkINDITimeout();
0408 
0409         // Logs
0410         void updateDebugInterfaces();
0411         void watchDebugProperty(INDI::Property prop);
0412 
0413         void addMount(ISD::Mount *device);
0414         void addCamera(ISD::Camera *device);
0415         void addFilterWheel(ISD::FilterWheel *device);
0416         void addFocuser(ISD::Focuser *device);
0417         void addRotator(ISD::Rotator *device);
0418         void addDome(ISD::Dome *device);
0419         void addWeather(ISD::Weather *device);
0420         void addDustCap(ISD::DustCap *device);
0421         void addLightBox(ISD::LightBox *device);
0422         void addGuider(ISD::Guider *device);
0423         void addGPS(ISD::GPS *device);
0424 
0425         /**
0426          * @brief syncGenericDevice Check if this device needs to be added to any Ekos module.
0427          * @param device pointer to generic device.
0428          */
0429         void syncGenericDevice(const QSharedPointer<ISD::GenericDevice> &device);
0430         void createModules(const QSharedPointer<ISD::GenericDevice> &device);
0431 
0432         // Profiles
0433         void addProfile();
0434         void editProfile();
0435         void deleteProfile();
0436         void wizardProfile();
0437 
0438         // Mount Summary
0439         void updateMountCoords(const SkyPoint position, ISD::Mount::PierSide pierSide, const dms &ha);
0440         void updateMountStatus(ISD::Mount::Status status);
0441         void setTarget(const QString &name);
0442 
0443         // Capture Summary
0444         void updateCaptureStatus(CaptureState status);
0445         void updateCaptureProgress(SequenceJob *job, const QSharedPointer<FITSData> &data);
0446         void updateExposureProgress(SequenceJob *job);
0447         void updateCaptureCountDown();
0448 
0449         // Focus summary
0450         void updateFocusStatus(FocusState status);
0451         void updateCurrentHFR(double newHFR, int position);
0452 
0453         // Guide Summary
0454         void updateGuideStatus(GuideState status);
0455         void updateSigmas(double ra, double de);
0456 
0457     private:
0458         explicit Manager(QWidget *parent);
0459         ~Manager() override;
0460 
0461         void removeTabs();
0462         void reset();
0463         void initCapture();
0464         void initFocus();
0465         void initGuide();
0466         void initAlign();
0467         void initMount();
0468         void initObservatory();
0469 
0470         void loadDrivers();
0471         void loadProfiles();
0472         int addModuleTab(EkosModule module, QWidget *tab, const QIcon &icon);
0473 
0474         /**
0475          * @brief syncActiveDevices Syncs ACTIVE_DEVICES such as ACTIVE_TELESCOPE and ACTIVE_CCD
0476          * to the currently detected devices.
0477          */
0478         void syncActiveDevices();
0479 
0480         /**
0481          * @brief isINDIReady Check whether all INDI devices are connected and ready and emit signals accordingly.
0482          * @return True if all INDI devices are connected and ready.
0483          */
0484         bool isINDIReady();
0485 
0486         // Connect Signals/Slots of Ekos modules
0487         void connectModules();
0488 
0489         // Check if INDI server is already running
0490         bool isRunning(const QString &process);
0491 
0492         bool getCurrentProfile(QSharedPointer<ProfileInfo> &profile) const;
0493         void updateProfileLocation(const QSharedPointer<ProfileInfo> &profile);
0494         void setProfileMapping(const QJsonObject &payload)
0495         {
0496             m_ProfileMapping = payload;
0497         }
0498         // Port Selector Save profile when connect all is pressed
0499         void setPortSelectionComplete();
0500         // Check if the driver binary must be one only to avoid duplicate instances
0501         // Some driver binaries support multiple devices per binary
0502         // so we only need to start a single instance to handle them all.
0503         bool checkUniqueBinaryDriver(DriverInfo * primaryDriver, DriverInfo * secondaryDriver);
0504 
0505         // Containers
0506 
0507         // All Drivers
0508         QHash<QString, DriverInfo *> driversList;
0509 
0510         // All managed drivers
0511         QList<DriverInfo *> managedDrivers;
0512 
0513         // Smart pointers for the various Ekos Modules
0514         std::unique_ptr<Capture> captureProcess;
0515         std::unique_ptr<Focus> focusProcess;
0516         std::unique_ptr<Guide> guideProcess;
0517         std::unique_ptr<Align> alignProcess;
0518         std::unique_ptr<Mount> mountProcess;
0519         std::unique_ptr<Analyze> analyzeProcess;
0520         std::unique_ptr<Scheduler> schedulerProcess;
0521         std::unique_ptr<Observatory> observatoryProcess;
0522         std::unique_ptr<EkosLive::Client> ekosLiveClient;
0523 
0524         bool m_LocalMode { true };
0525         bool m_isStarted { false };
0526         bool m_RemoteManagerStart { false };
0527 
0528         int m_DriverDevicesCount { 0 };
0529 
0530         QStringList m_LogText;
0531         KPageWidgetItem *ekosOptionsWidget { nullptr };
0532         OpsEkos *opsEkos { nullptr };
0533 
0534         CommunicationStatus m_ekosStatus { Ekos::Idle };
0535         CommunicationStatus m_indiStatus { Ekos::Idle };
0536         // Settle is used to know once all properties from all devices have been defined
0537         // There is no way to know this for sure so we use a debounace mechanism.
0538         CommunicationStatus m_settleStatus { Ekos::Idle };
0539 
0540         std::unique_ptr<QStandardItemModel> profileModel;
0541         QList<QSharedPointer<ProfileInfo>> profiles;
0542         QJsonObject m_ProfileMapping;
0543 
0544         // Mount Summary
0545         QPointer<QProcess> indiHubAgent;
0546         KLed *mountMotionState { nullptr };
0547 
0548 
0549         // Capture Summary
0550         QTimer m_CountdownTimer;
0551         QTimer settleTimer;
0552         // Preview Frame
0553         QSharedPointer<SummaryFITSView> m_SummaryView;
0554 
0555         QSharedPointer<ProfileInfo> m_CurrentProfile;
0556         bool profileWizardLaunched { false };
0557         QString m_PrimaryCamera, m_GuideCamera;
0558 
0559         // Port Selector
0560         std::unique_ptr<Selector::Dialog> m_PortSelector;
0561         QTimer m_PortSelectorTimer;
0562 
0563         QMap<QString, QSharedPointer<FilterManager>> m_FilterManagers;
0564 
0565         // Logs
0566         QPointer<OpsLogs> opsLogs;
0567 
0568         // E.g. Setup, Scheduler, and Analyze.
0569         int numPermanentTabs { 0 };
0570 
0571         friend class EkosLive::Client;
0572         friend class EkosLive::Message;
0573         friend class EkosLive::Media;
0574 
0575         static Manager *_Manager;
0576 };
0577 
0578 }