Kstars

manager.h
1 /*
2  SPDX-FileCopyrightText: 2012 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #ifdef USE_QT5_INDI
10 #include <baseclientqt.h>
11 #else
12 #include <baseclient.h>
13 #endif
14 
15 #include "ui_manager.h"
16 
17 #include "ekos.h"
18 #include "manager/focusmanager.h"
19 #include "manager/guidemanager.h"
20 #include "fitsviewer/summaryfitsview.h"
21 #include "align/align.h"
22 #include "capture/capture.h"
23 #include "focus/focus.h"
24 #include "guide/guide.h"
25 #include "indi/indistd.h"
26 #include "mount/mount.h"
27 #include "scheduler/scheduler.h"
28 #include "analyze/analyze.h"
29 //#include "observatory/observatory.h"
30 #include "auxiliary/filtermanager.h"
31 #include "auxiliary/portselector.h"
32 #include "ksnotification.h"
33 // Can't use forward declaration with QPointer. QTBUG-29588
34 #include "auxiliary/opslogs.h"
35 
36 #include <QDialog>
37 #include <QHash>
38 #include <QtDBus/QtDBus>
39 
40 #include <memory>
41 
42 //! Generic record interfaces and implementations.
43 namespace EkosLive
44 {
45 class Client;
46 class Message;
47 class Media;
48 }
49 
50 class DriverInfo;
51 class ProfileInfo;
53 
54 /**
55  * @class Manager
56  * @short Primary class to handle all Ekos modules.
57  * 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.
58  * \defgroup EkosDBusInterface "Ekos DBus Interface" provides high level functions to control devices and Ekos modules for a total robotic operation:
59  * <ul>
60  * <li>\ref CaptureDBusInterface "Capture Module DBus Interface"</li>
61  * <li>\ref FocusDBusInterface "Focus Module DBus Interface"</li>
62  * <li>\ref MountDBusInterface "Mount Module DBus Interface"</li>
63  * <li>\ref GuideDBusInterface "Guide Module DBus Interface"</li>
64  * <li>\ref AlignDBusInterface "Align Module DBus Interface"</li>
65  * <li>\ref WeatherDBusInterface "Weather DBus Interface"</li>
66  * <li>\ref DustCapDBusInterface "Dust Cap DBus Interface"</li>
67  * </ul>
68  * For low level access to INDI devices, the \ref INDIDBusInterface "INDI Dbus Interface" provides complete access to INDI devices and properties.
69  * Ekos Manager provides a summary of operations progress in the <i>Summary</i> section of the <i>Setup</i> tab.
70  *
71  * @author Jasem Mutlaq
72  * @version 1.8
73  */
74 namespace Ekos
75 {
76 
77 class Manager : public QDialog, public Ui::Manager
78 {
79  Q_OBJECT
80  Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.Ekos")
81 
82  Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus indiStatus READ indiStatus NOTIFY indiStatusChanged)
83  Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus ekosStatus READ ekosStatus NOTIFY ekosStatusChanged)
84  Q_SCRIPTABLE Q_PROPERTY(Ekos::CommunicationStatus settleStatus READ settleStatus NOTIFY settleStatusChanged)
85  Q_SCRIPTABLE Q_PROPERTY(bool ekosLiveStatus READ ekosLiveStatus NOTIFY ekosLiveStatusChanged)
86  Q_SCRIPTABLE Q_PROPERTY(QStringList logText READ logText NOTIFY newLog)
87 
88  enum class EkosModule
89  {
90  Setup,
91  Scheduler,
92  Analyze,
93  Capture,
94  Focus,
95  Mount,
96  Align,
97  Guide,
98  Observatory,
99  };
100  public:
101  static Manager *Instance();
102  static void release();
103 
104  // No OP
105  void initialize() {}
106 
107  void appendLogText(const QString &);
108  void setOptionsWidget(KPageWidgetItem *ops)
109  {
110  ekosOptionsWidget = ops;
111  }
112  void addObjectToScheduler(SkyObject *object);
113 
114  Scheduler *schedulerModule()
115  {
116  return schedulerProcess.get();
117  }
118  Guide *guideModule()
119  {
120  return guideProcess.get();
121  }
122  Align *alignModule()
123  {
124  return alignProcess.get();
125  }
126  Mount *mountModule()
127  {
128  return mountProcess.get();
129  }
130  Focus *focusModule()
131  {
132  return focusProcess.get();
133  }
134  Capture *captureModule()
135  {
136  return captureProcess.get();
137  }
138  FITSView *getSummaryPreview()
139  {
140  return m_SummaryView.get();
141  }
142  FilterManager *getFilterManager()
143  {
144  return filterManager.data();
145  }
146  QString getCurrentJobName();
147  void announceEvent(const QString &message, KSNotification::EventType event);
148 
149  /**
150  * @brief activateModule Switch tab to specific module name (i.e. CCD) and raise Ekos screen to focus.
151  * @param name module name CCD, Guide, Focus, Mount, Scheduler, or Observatory.
152  * @param popup if True, show Ekos Manager window in the foreground.
153  */
154  void activateModule(const QString &name, bool popup = false);
155 
156  /**
157  * @brief addProfile Add a new profile to the database.
158  * @param profileInfo Collection of profile parameters to include the following:
159  * 1. name: Profile name
160  * 2. auto_connect: True of False for Autoconnect?
161  * 3. Mode: "local" or "remote"
162  * 4. remote_host: Optional. remote host (default localhost)
163  * 5. remote_port: Optional. remote port (default 7624)
164  * 6. guiding: 0 for "Internal", 1 for "PHD2", or 2 for "LinGuider"
165  * 7. remote_guiding_host: Optional. remote host for guider application (default localhost)
166  * 8. remote_guide_port: Optional. remote port for guider application.
167  * 9. use_web_manager: True or False?
168  * 10. web_manager_port. Optional. INDI Web Manager port (default 8624)
169  * 12. primary_scope: ID of primary scope to use. This is the ID from OAL::Scope list in the database.
170  * 13. guide_scope: ID of guide scope to use. This is the ID from OAL::Scope list in the database.
171  * 14. mount: Mount driver label (default --).
172  * 15. ccd: CCD driver label (default --).
173  * 16. guider: Guider driver label (default --).
174  * 17. focuser: Focuser driver label (default --).
175  * 18. filter: Filter Wheel driver label (default --).
176  * 19. ao: Adaptive Optics driver label (default --).
177  * 20. dome: Dome driver label (default --).
178  * 21. Weather: Weather station driver label (default --).
179  * 22. aux1: aux1 driver label (default --).
180  * 23. aux2: aux2 driver label (default --).
181  * 24. aux3: aux3 driver label (default --).
182  * 25. aux4: aux4 driver label (default --).
183  */
184  void addNamedProfile(const QJsonObject &profileInfo);
185 
186  /** Same as above, except it edits an existing named profile */
187  void editNamedProfile(const QJsonObject &profileInfo);
188 
189  /**
190  * @brief deleteProfile Delete existing equipment profile
191  * @param name Name of profile
192  * @warning Ekos must be stopped for this to work. It will fail if Ekos is online.
193  */
194  void deleteNamedProfile(const QString &name);
195 
196  /**
197  * @brief getProfile Get a single profile information.
198  * @param name Profile name
199  * @return A JSon object with the detail profile info as described in addProfile function.
200  */
201  QJsonObject getNamedProfile(const QString &name);
202 
203  /**
204  * DBus commands to manage equipment profiles.
205  */
206 
207  /*@{*/
208 
209  /**
210  * DBUS interface function.
211  * set Current device profile.
212  * @param profileName Profile name
213  * @return True if profile is set, false if not found.
214  */
215  Q_SCRIPTABLE bool setProfile(const QString &profileName);
216 
217  /**
218  * DBUS interface function
219  * @brief getProfiles Return a list of all device profiles
220  * @return List of device profiles
221  */
222  Q_SCRIPTABLE QStringList getProfiles();
223 
224  /** @}*/
225 
226 
227  /**
228  * Manager interface provides advanced scripting capabilities to establish and shutdown Ekos services.
229  */
230 
231  /*@{*/
232 
233  /**
234  * DBUS interface function.
235  * @return INDI connection status (0 Idle, 1 Pending, 2 Connected, 3 Error)
236  * @deprecated
237  */
238  Q_SCRIPTABLE unsigned int getINDIConnectionStatus()
239  {
240  return m_indiStatus;
241  }
242 
243  Q_SCRIPTABLE Ekos::CommunicationStatus indiStatus()
244  {
245  return m_indiStatus;
246  }
247 
248  /**
249  * DBUS interface function.
250  * @return Ekos starting status (0 Idle, 1 Pending, 2 Started, 3 Error)
251  * @deprecated
252  */
253  Q_SCRIPTABLE unsigned int getEkosStartingStatus()
254  {
255  return m_ekosStatus;
256  }
257 
258  Q_SCRIPTABLE Ekos::CommunicationStatus ekosStatus()
259  {
260  return m_ekosStatus;
261  }
262 
263  /**
264  * DBUS interface function.
265  * @return Settle status (0 Idle, 1 Pending, 2 Started, 3 Error)
266  */
267  Q_SCRIPTABLE Ekos::CommunicationStatus settleStatus()
268  {
269  return m_settleStatus;
270  }
271 
272  /**
273  * DBUS interface function. Toggle Ekos logging.
274  * @param name Name of logging to toggle. Available options are:
275  * ** VERBOSE
276  * ** INDI
277  * ** FITS
278  * ** CAPTURE
279  * ** FOCUS
280  * ** GUIDE
281  * ** ALIGNMENT
282  * ** MOUNT
283  * ** SCHEDULER
284  * ** OBSERVATORY
285  * @param enabled True to enable, false otherwise.
286  */
287  Q_SCRIPTABLE Q_NOREPLY void setEkosLoggingEnabled(const QString &name, bool enabled);
288 
289  /**
290  * DBUS interface function.
291  * 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,
292  * it establishes connection to the remote INDI server.
293  * @return Returns true if server started successful (local mode) or connection to remote server is successful (remote mode).
294  */
295  Q_SCRIPTABLE void start();
296 
297  /**
298  * DBUS interface function.
299  * If connection mode is local, the function terminates the local INDI server and drivers. For remote, it disconnects from the remote INDI server.
300  */
301  Q_SCRIPTABLE void stop();
302 
303  Q_SCRIPTABLE QStringList logText()
304  {
305  return m_LogText;
306  }
307 
308  Q_SCRIPTABLE bool ekosLiveStatus();
309 
310  /**
311  * DBUS interface function.
312  * @param enabled Connect to EkosLive if true, otherwise disconnect.
313  */
314  Q_SCRIPTABLE void setEkosLiveConnected(bool enabled);
315 
316  /**
317  * @brief setEkosLiveConfig Set EkosLive settings
318  * @param onlineService If true, connect to EkosLive Online Service. Otherwise, EkosLive offline service.
319  * @param rememberCredentials Remember username and password for next session.
320  * @param autoConnect If true, it will automatically connect to EkosLive service.
321  */
322  Q_SCRIPTABLE void setEkosLiveConfig(bool onlineService, bool rememberCredentials, bool autoConnect);
323 
324  /**
325  * @brief setEkosLiveUser Save EkosLive username and password
326  * @param username User name
327  * @param password Password
328  */
329  Q_SCRIPTABLE void setEkosLiveUser(const QString &username, const QString &password);
330 
331  /**
332  * @brief acceptPortSelection Accept current port selection settings in the Selector Dialog
333  */
334  Q_SCRIPTABLE void acceptPortSelection();
335 
336  signals:
337  // Have to use full Ekos::CommunicationStatus for DBus signal to work
338  void ekosStatusChanged(Ekos::CommunicationStatus status);
339  void indiStatusChanged(Ekos::CommunicationStatus status);
340  void settleStatusChanged(Ekos::CommunicationStatus status);
341  void ekosLiveStatusChanged(bool status);
342 
343  void newLog(const QString &text);
344  void newModule(const QString &name);
345 
346  protected:
347  void closeEvent(QCloseEvent *event) override;
348  void hideEvent(QHideEvent *) override;
349  void showEvent(QShowEvent *) override;
350  void resizeEvent(QResizeEvent *) override;
351 
352  public slots:
353 
354  /**
355  * DBUS interface function.
356  * Connects all the INDI devices started by Ekos.
357  */
358  Q_SCRIPTABLE Q_NOREPLY void connectDevices();
359 
360  /**
361  * DBUS interface function.
362  * Disconnects all the INDI devices started by Ekos.
363  */
364  Q_SCRIPTABLE Q_NOREPLY void disconnectDevices();
365 
366  /** @}*/
367 
368  void processINDI();
369  void cleanDevices(bool stopDrivers = true);
370 
371  void processNewDevice(ISD::GenericDevice *device);
372  void processNewProperty(INDI::Property);
373  void processDeleteProperty(const QString &name);
374  void setDeviceReady();
375 
376  void processNewNumber(INumberVectorProperty *nvp);
377  void processNewText(ITextVectorProperty *tvp);
378  void processNewSwitch(ISwitchVectorProperty *svp);
379  void processNewLight(ILightVectorProperty *lvp);
380  void processNewBLOB(IBLOB *bvp);
381 
382  void restartDriver(const QString &deviceName);
383 
384  private slots:
385 
386  void changeAlwaysOnTop(Qt::ApplicationState state);
387 
388  void showEkosOptions();
389 
390  void updateLog();
391  void clearLog();
392 
393  void processTabChange();
394 
395  void setServerStarted(const QString &host, int port);
396  void setServerFailed(const QString &host, int port, const QString &message);
397  //void setServerTerminated(const QString &host, int port, const QString &message);
398 
399  void setClientStarted(const QString &host, int port);
400  void setClientFailed(const QString &host, int port, const QString &message);
401  void setClientTerminated(const QString &host, int port, const QString &message);
402 
403  void removeDevice(ISD::GenericDevice *device);
404 
405  const QList<ISD::GenericDevice *> getAllDevices() const
406  {
407  return m_GenericDevices;
408  }
409 
410  void deviceConnected();
411  void deviceDisconnected();
412 
413  //void processINDIModeChange();
414  void checkINDITimeout();
415 
416  // Logs
417  void updateDebugInterfaces();
418  void watchDebugProperty(ISwitchVectorProperty *svp);
419 
420  void addMount(ISD::Mount *device);
421  void addCamera(ISD::Camera *device);
422  void addFilterWheel(ISD::FilterWheel *device);
423  void addFocuser(ISD::Focuser *device);
424  void addRotator(ISD::Rotator *device);
425  void addDome(ISD::Dome *device);
426  void addWeather(ISD::Weather *device);
427  void addDustCap(ISD::DustCap *device);
428  void addLightBox(ISD::LightBox *device);
429  void addGuider(ISD::Guider *device);
430  void addGPS(ISD::GPS *device);
431 
432  /**
433  * @brief syncGenericDevice Check if this device needs to be added to any Ekos module.
434  * @param device pointer to generic device.
435  */
436  void syncGenericDevice(ISD::GenericDevice *device);
437  void createModules(ISD::GenericDevice *device);
438 
439  // Profiles
440  void addProfile();
441  void editProfile();
442  void deleteProfile();
443  void wizardProfile();
444 
445  // Mount Summary
446  void updateMountCoords(const SkyPoint position, ISD::Mount::PierSide pierSide, const dms &ha);
447  void updateMountStatus(ISD::Mount::Status status);
448  void setTarget(SkyObject *o);
449 
450  // Capture Summary
451  void updateCaptureStatus(CaptureState status);
452  void updateCaptureProgress(SequenceJob *job, const QSharedPointer<FITSData> &data);
453  void updateExposureProgress(SequenceJob *job);
454  void updateCaptureCountDown();
455 
456  // Focus summary
457  void updateFocusStatus(FocusState status);
458  void updateCurrentHFR(double newHFR, int position);
459 
460  // Guide Summary
461  void updateGuideStatus(GuideState status);
462  void updateSigmas(double ra, double de);
463 
464  private:
465  explicit Manager(QWidget *parent);
466  ~Manager() override;
467 
468  void removeTabs();
469  void reset();
470  void initCapture();
471  void initFocus();
472  void initGuide();
473  void initAlign();
474  void initMount();
475  //void initObservatory();
476 
477  void loadDrivers();
478  void loadProfiles();
479  int addModuleTab(EkosModule module, QWidget *tab, const QIcon &icon);
480 
481  /**
482  * @brief syncActiveDevices Syncs ACTIVE_DEVICES such as ACTIVE_TELESCOPE and ACTIVE_CCD
483  * to the currently detected devices.
484  */
485  void syncActiveDevices();
486 
487  // Connect Signals/Slots of Ekos modules
488  void connectModules();
489 
490  // Check if INDI server is already running
491  bool isRunning(const QString &process);
492 
493  ProfileInfo *getCurrentProfile();
494  void getCurrentProfileTelescopeInfo(double &primaryFocalLength, double &primaryAperture, double &guideFocalLength,
495  double &guideAperture);
496  void updateProfileLocation(ProfileInfo *pi);
497  void setProfileMapping(const QJsonObject &payload)
498  {
499  m_ProfileMapping = payload;
500  }
501  // Port Selector Save profile when connect all is pressed
502  void setPortSelectionComplete();
503  // Check if the driver binary must be one only to avoid duplicate instances
504  // Some driver binaries support multiple devices per binary
505  // so we only need to start a single instance to handle them all.
506  bool checkUniqueBinaryDriver(DriverInfo * primaryDriver, DriverInfo * secondaryDriver);
507 
508  QList<ISD::GenericDevice *> findDevicesByInterface(uint32_t interface);
509 
510  // Containers
511 
512  // All Drivers
513  QHash<QString, DriverInfo *> driversList;
514 
515  // All managed drivers
516  QList<DriverInfo *> managedDrivers;
517 
518  // All generic devices (i.e. those define by INDI server)
519  QList<ISD::GenericDevice *> m_GenericDevices;
520 
521  // Smart pointers for the various Ekos Modules
522  std::unique_ptr<Capture> captureProcess;
523  std::unique_ptr<Focus> focusProcess;
524  std::unique_ptr<Guide> guideProcess;
525  std::unique_ptr<Align> alignProcess;
526  std::unique_ptr<Mount> mountProcess;
527  std::unique_ptr<Analyze> analyzeProcess;
528  std::unique_ptr<Scheduler> schedulerProcess;
529  // FIXME migrate
530  //std::unique_ptr<Observatory> observatoryProcess;
531  std::unique_ptr<EkosLive::Client> ekosLiveClient;
532 
533  bool m_LocalMode { true };
534  bool m_isStarted { false };
535  bool m_RemoteManagerStart { false };
536 
537  int nDevices { 0 };
538 
539  QStringList m_LogText;
540  KPageWidgetItem *ekosOptionsWidget { nullptr };
541 
542  CommunicationStatus m_ekosStatus { Ekos::Idle };
543  CommunicationStatus m_indiStatus { Ekos::Idle };
544  // Settle is used to know once all properties from all devices have been defined
545  // There is no way to know this for sure so we use a debounace mechanism.
546  CommunicationStatus m_settleStatus { Ekos::Idle };
547 
548  std::unique_ptr<QStandardItemModel> profileModel;
550  QJsonObject m_ProfileMapping;
551 
552  // Filter Manager
553  QSharedPointer<FilterManager> filterManager;
554 
555  // Mount Summary
556  QPointer<QProcess> indiHubAgent;
557 
558  // Capture Summary
559  QTimer m_CountdownTimer;
560  QTimer settleTimer;
561  // Preview Frame
562  QSharedPointer<SummaryFITSView> m_SummaryView;
563 
564  ProfileInfo *currentProfile { nullptr };
565  bool profileWizardLaunched { false };
566  QString m_PrimaryCamera, m_GuideCamera;
567 
568  // Port Selector
569  std::unique_ptr<Selector::Dialog> m_PortSelector;
570  QTimer m_PortSelectorTimer;
571 
572  // Logs
573  QPointer<OpsLogs> opsLogs;
574 
575  // E.g. Setup, Scheduler, and Analyze.
576  int numPermanentTabs { 0 };
577 
578  friend class EkosLive::Client;
579  friend class EkosLive::Message;
580  friend class EkosLive::Media;
581 
582  static Manager *_Manager;
583 };
584 
585 }
virtual void release(quint64 objid)
Ekos is an advanced Astrophotography tool for Linux. It is based on a modular extensible framework to...
Definition: align.cpp:70
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
Sequence Job is a container for the details required to capture a series of images.
Definition: sequencejob.h:18
CaptureState
Capture states.
Definition: ekos.h:91
KGuiItem stop()
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
ScriptableExtension * host() const
Generic record interfaces and implementations.
Definition: cloud.cpp:23
KGuiItem reset()
ApplicationState
Information about an object in the sky.
Definition: skyobject.h:41
QString message
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:55 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.