Kstars

scheduler.h
1/*
2 SPDX-FileCopyrightText: 2015 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 DBus calls from GSoC 2015 Ekos Scheduler project:
5 SPDX-FileCopyrightText: 2015 Daniel Leu <daniel_mihai.leu@cti.pub.ro>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#pragma once
11
12#include "ui_scheduler.h"
13#include "opsoffsetsettings.h"
14#include "opsalignmentsettings.h"
15#include "opsjobssettings.h"
16#include "opsscriptssettings.h"
17#include "schedulertypes.h"
18#include "ekos/align/align.h"
19#include "indi/indiweather.h"
20#include "schedulerjob.h"
21
22#include <lilxml.h>
23
24#include <QTime>
25#include <QTimer>
26#include <QUrl>
27#include <QtDBus/QDBusInterface>
28
29#include <cstdint>
30
32
33class GeoLocation;
34class SkyObject;
35class KConfigDialog;
36class TestSchedulerUnit;
37class SolverUtils;
38class TestEkosSchedulerOps;
39
40namespace Ekos
41{
42
43class SequenceJob;
44class GreedyScheduler;
46class SchedulerModuleState;
47class SequenceEditor;
48
49/**
50 * @brief The Ekos scheduler is a simple scheduler class to orchestrate automated multi object observation jobs.
51 * @author Jasem Mutlaq
52 * @version 1.2
53 */
54class Scheduler : public QWidget, public Ui::Scheduler
55{
57
58 friend class FramingAssistantUI;
59
60 public:
61
62 /** @brief Columns, in the same order as UI. */
63 typedef enum
64 {
65 SCHEDCOL_NAME = 0,
66 SCHEDCOL_STATUS,
67 SCHEDCOL_CAPTURES,
68 SCHEDCOL_ALTITUDE,
69 SCHEDCOL_STARTTIME,
70 SCHEDCOL_ENDTIME,
72
73 /** @brief Constructor, the starndard scheduler constructor. */
74 Scheduler();
75 /** @brief DebugConstructor, a constructor used in testing with a mock ekos. */
76 Scheduler(const QString path, const QString interface,
77 const QString &ekosPathStr, const QString &ekosInterfaceStr);
78 ~Scheduler() = default;
79
80 QString getCurrentJobName();
81
82 // shortcut
83 SchedulerJob *activeJob();
84
85 /**
86 * @brief handleConfigChanged Update UI after changes to the global configuration
87 */
89
90 void addObject(SkyObject *object);
91
92 /**
93 * @brief importMosaic Import mosaic into planner and generate jobs for the scheduler.
94 * @param payload metadata for the mosaic information.
95 * @note Only Telescopius.com mosaic format is now supported.
96 */
97 bool importMosaic(const QJsonObject &payload);
98
99 /** @defgroup SchedulerDBusInterface Ekos DBus Interface - Scheduler Module
100 * Ekos::Align interface provides primary functions to run and stop the scheduler.
101 */
102
103 /*@{*/
104
105 /**
106 * @brief Set the file URL pointing to the capture sequence file
107 * @param sequenceFileURL URL of the capture sequence file
108 */
109 void setSequence(const QString &sequenceFileURL);
110
111 /**
112 * @brief prepareGUI Perform once only GUI prep processing
113 */
114 void prepareGUI();
115
116 // Settings popup
117 OpsOffsetSettings *m_OpsOffsetSettings { nullptr };
118 OpsAlignmentSettings *m_OpsAlignmentSettings { nullptr };
119 OpsJobsSettings *m_OpsJobsSettings { nullptr };
120 OpsScriptsSettings *m_OpsScriptsSettings { nullptr };
121
122
123 /** DBUS interface function.
124 * @brief Resets all jobs to IDLE
125 */
126 Q_SCRIPTABLE void sortJobsPerAltitude();
127
128 void setProfile(const QString &profile)
129 {
130 schedulerProfileCombo->setCurrentText(profile);
131 }
132 QString profile()
133 {
134 return schedulerProfileCombo->currentText();
135 }
136
137 /**
138 * @brief retrieve the error handling strategy from the UI
139 */
141
142 /**
143 * @brief select the error handling strategy (no restart, restart after all terminated, restart immediately)
144 */
146
147 /** @}*/
148
149 // TODO: This section of static public and private methods should someday
150 // be moved from Scheduler and placed in a separate class,
151 // e.g. SchedulerPlanner or SchedulerJobEval
152 /**
153 * @brief Remove a job from current table row.
154 * @param index
155 */
156 void removeJob();
157
158 /**
159 * @brief Remove a job by selecting a table row.
160 * @param index
161 */
162 void removeOneJob(int index);
163
164 /**
165 * @brief addJob Add a new job from form values
166 */
167 Q_INVOKABLE void addJob(SchedulerJob *job = nullptr);
168 /**
169 * @brief addJob Add a new job from form values
170 */
171 Q_INVOKABLE void updateJob(int index = -1);
172
173 /**
174 * @brief createJob Create a new job from form values.
175 * @param job job to be filled from UI values
176 * @return true iff update was successful
177 */
178 bool fillJobFromUI(SchedulerJob *job);
179
180 /**
181 * @brief addToQueue Construct a SchedulerJob and add it to the queue or save job settings from current form values.
182 * jobUnderEdit determines whether to add or edit
183 */
184 void saveJob(SchedulerJob *job = nullptr);
185
186 void toggleScheduler();
187
188 QJsonObject getSchedulerSettings();
189
190 /**
191 * @brief settleSettings Run this function after timeout from debounce timer to update database
192 * and emit settingsChanged signal. This is required so we don't overload output.
193 */
194 void settleSettings();
195
196 // the state machine
197 QSharedPointer<SchedulerModuleState> moduleState() const
198 {
199 return m_moduleState;
200 }
201 // the process engine
202 QSharedPointer<SchedulerProcess> process()
203 {
204 return m_process;
205 }
206
207 /**
208 * @brief saveFile Save scheduler jobs to disk
209 * @param path Path to esl file to save jobs to
210 * @return True if successful, false otherwise
211 */
212 bool saveFile(const QUrl &path);
213
214 /**
215 * @brief loadFile Load scheduler jobs from disk
216 * @param path Oath to esl file to load jobs from
217 * @return True if successful, false otherwise
218 */
219 bool loadFile(const QUrl &path);
220
221 // Settings
222 QVariantMap getAllSettings() const;
223 void setAllSettings(const QVariantMap &settings);
224
225 private:
226
227 void setAlgorithm(int alg);
228
229 friend TestSchedulerUnit;
230
231 // TODO: See above TODO. End of static methods that might be moved to
232 // a separate Scheduler-related class.
233
234 /*@{*/
235 /** @internal Safeguard flag to avoid registering signals from widgets multiple times.
236 */
237 bool jobChangesAreWatched { false };
238
239 protected:
240
241 /** @internal Enables signal watch on SchedulerJob form values in order to apply changes to current job.
242 * @param enable is the toggle flag, true to watch for changes, false to ignore them.
243 */
244 void watchJobChanges(bool enable);
245
246 /** @internal Marks the currently selected SchedulerJob as modified change.
247 *
248 * This triggers job re-evaluation.
249 * Next time save button is invoked, the complete content is written to disk.
250 */
251 void setDirty();
252 /** @} */
253
254 /**
255 * @brief updateJobTable Update the job's row in the job table. If the row does not exist, it will
256 * be created on the fly. If job is null, update the entire table
257 * @param job
258 */
259 void updateJobTable(SchedulerJob *job = nullptr);
260
261 /**
262 * @brief insertJobTableRow Insert a new row (empty) into the job table
263 * @param row row number (starting with 0)
264 * @param above insert above the given row (=true) or below (=false)
265 */
266 void insertJobTableRow(int row, bool above = true);
267
268 /**
269 * @brief Update the style of a cell, depending on the job's state
270 */
271 void updateCellStyle(SchedulerJob *job, QTableWidgetItem *cell);
272
273 protected slots:
274
275 /**
276 * @brief checkInterfaceReady Sometimes syncProperties() is not sufficient since the ready signal could have fired already
277 * and cannot be relied on to know once a module interface is ready. Therefore, we explicitly check if the module interface
278 * is ready.
279 * @param iface interface to test for readiness.
280 */
281 void interfaceReady(QDBusInterface *iface);
282
283 void setWeatherStatus(ISD::Weather::Status status);
284
285 /**
286 * @brief select object from KStars's find dialog.
287 */
288 void selectObject();
289
290 /**
291 * @brief Selects FITS file for solving.
292 */
293 void selectFITS();
294
295 /**
296 * @brief Selects sequence queue.
297 */
298 void selectSequence();
299
300 /**
301 * @brief Selects sequence queue.
302 */
303 void selectStartupScript();
304
305 /**
306 * @brief Selects sequence queue.
307 */
309
310 /**
311 * @brief editJob Edit an observation job
312 * @param i index model in queue table
313 */
314 Q_INVOKABLE void loadJob(QModelIndex i);
315
316 Q_INVOKABLE bool modifyJob(int index = -1);
317
318 /**
319 * @brief updateSchedulerURL Update scheduler URL after succesful loading a new file.
320 */
321 void updateSchedulerURL(const QString &fileURL);
322
323 /**
324 * @brief setJobAddApply Set first button state to add new job or apply changes.
325 */
326 void setJobAddApply(bool add_mode);
327
328 /**
329 * @brief setJobManipulation Enable or disable job manipulation buttons.
330 */
331 void setJobManipulation(bool can_reorder, bool can_delete, bool is_lead);
332
333 /**
334 * @brief set all GUI fields to the values of the given scheduler job
335 */
336 void syncGUIToJob(SchedulerJob *job);
337
338 /**
339 * @brief syncGUIToGeneralSettings set all UI fields that are not job specific
340 */
342
343 /**
344 * @brief jobSelectionChanged Update UI state when the job list is clicked once.
345 */
346 void clickQueueTable(QModelIndex index);
347
348 /**
349 * @brief clearJobTable delete all rows in the job table
350 */
352
353 /**
354 * @brief clearLog Clears log entry
355 */
356 Q_INVOKABLE void clearLog();
357
358 /**
359 * @brief Update scheduler parameters to the currently selected scheduler job
360 * @param selected table position
361 * @param deselected table position
362 */
363 void queueTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
364
365 /**
366 * @brief reorderJobs Change the order of jobs in the UI based on a subset of its jobs.
367 */
368 bool reorderJobs(QList<SchedulerJob*> reordered_sublist);
369
370 /**
371 * @brief moveJobUp Move the selected job up in the job list.
372 */
373 void moveJobUp();
374
375 /**
376 * @brief moveJobDown Move the selected job down in the list.
377 */
378 void moveJobDown();
379
380 /**
381 * @brief handleSchedulerSleeping Update UI if scheduler is set to sleep
382 * @param shutdown flag if a preemptive shutdown is executed
383 * @param sleep flag if the scheduler will sleep
384 */
385 void handleSchedulerSleeping(bool shutdown, bool sleep);
386
387 /**
388 * @brief handleSchedulerStateChanged Update UI when the scheduler state changes
389 */
390 void handleSchedulerStateChanged(SchedulerState newState);
391
392 /**
393 * @brief handleSetPaused Update the UI when {@see #setPaused()} is called.
394 */
395 void handleSetPaused();
396
397 void pause();
398 bool save();
399 void saveAs();
400
401 /**
402 * @brief load Open a file dialog to select an ESL file, and load its contents.
403 * @param clearQueue Clear the queue before loading, or append ESL contents to queue.
404 * @param filename If not empty, this file will be used instead of poping up a dialog.
405 */
406 Q_INVOKABLE bool load(bool clearQueue, const QString &filename = QString());
407
408 Q_INVOKABLE void resetJobEdit();
409
410 /**
411 * @brief updateNightTime update the Twilight restriction with the argument job properties.
412 * @param job SchedulerJob for which to display the next dawn and dusk, or the job currently selected if null, or today's next dawn and dusk if no job is selected.
413 */
414 void updateNightTime(SchedulerJob const * job = nullptr);
415
416 /**
417 * @brief schedulerStopped React when the process engine has stopped the scheduler
418 */
419 void schedulerStopped();
420
421 /**
422 * @brief resumeCheckStatus If the scheduler primary loop was suspended due to weather or sleep event, resume it again.
423 */
424 void resumeCheckStatus();
425
426 /**
427 * @brief checkWeather Check weather status and act accordingly depending on the current status of the scheduler and running jobs.
428 */
429 //void checkWeather();
430
431 /**
432 * @brief displayTwilightWarning Display twilight warning to user if it is unchecked.
433 */
434 void checkTwilightWarning(bool enabled);
435
436 signals:
437 void newStatus(Ekos::SchedulerState state);
438 void weatherChanged(ISD::Weather::Status state);
439 void newTarget(const QString &);
440 // distance in arc-seconds measured by plate solving the a captured image and
441 // comparing that position to the target position.
442 void targetDistance(double distance);
443 // Below 2 are for the Analyze timeline.
444 void jobStarted(const QString &jobName);
445 void jobEnded(const QString &jobName, const QString &endReason);
446 void jobsUpdated(QJsonArray jobsList);
447 void settingsUpdated(const QVariantMap &settings);
448
449 private:
450 /**
451 * @brief handleJobsUpdated Update UI when jobs have been updated
452 * @param jobsList
453 */
454 void handleJobsUpdated(QJsonArray jobsList);
455
456 /**
457 * @brief handleShutdownStarted Show that the shutdown has been started.
458 */
459 void handleShutdownStarted();
460
461 /**
462 * @brief processFITSSelection When a FITS file is selected, open it and try to guess
463 * the object name, and its J2000 RA/DE to fill the UI with such info automatically.
464 */
465 void processFITSSelection(const QUrl &url);
466
467 /**
468 * @brief processCoordinates Parse coordinate values from UI.
469 * @return true if both values are valid
470 */
471 bool processCoordinates(dms &ra, dms &dec);
472
473 /**
474 * @brief updateProfiles React upon changed profiles and update the UI
475 */
476 void updateProfiles();
477
478 /**
479 * @brief readCoordsFromUI Helper function reading the target coordinates from the UI.
480 */
481 bool readCoordsFromUI();
482
483 /**
484 * @brief updateStageLabel Helper function that updates the stage label.
485 */
486 void updateJobStageUI(SchedulerJobStage stage);
487
488 // Target coordinates
489 void setTargetCoords(const dms ra, const dms dec, bool isJ2000 = true);
490 void displayTargetCoords();
491
492 ////////////////////////////////////////////////////////////////////
493 /// Settings
494 ////////////////////////////////////////////////////////////////////
495
496 /**
497 * @brief Connect GUI elements to sync settings once updated.
498 */
499 void connectSettings();
500 /**
501 * @brief Stop updating settings when GUI elements are updated.
502 */
503 void disconnectSettings();
504 /**
505 * @brief loadSettings Load setting from Options and set them accordingly.
506 */
507 void loadGlobalSettings();
508
509 /**
510 * @brief syncSettings When checkboxes, comboboxes, or spin boxes are updated, save their values in the
511 * global and per-train settings.
512 */
513 void syncSettings();
514
515 /**
516 * @brief syncControl Sync setting to widget. The value depends on the widget type.
517 * @param settings Map of all settings
518 * @param key name of widget to sync
519 * @param widget pointer of widget to set
520 * @return True if sync successful, false otherwise
521 */
522 bool syncControl(const QVariantMap &settings, const QString &key, QWidget * widget);
523
524 // ////////////////////////////////////////////////////////////////////
525 // Optical Train handling
526 // ////////////////////////////////////////////////////////////////////
527 void refreshOpticalTrain();
528
529 /**
530 * @brief checkJobInputComplete Check if all inputs are filled such that a new job could be added.
531 */
532 void checkJobInputComplete();
533
534 Ekos::Scheduler *ui { nullptr };
535
536 // Interface strings for the dbus. Changeable for mocks when testing. Private so only tests can change.
537 QString schedulerPathString { "/KStars/Ekos/Scheduler" };
538 QString kstarsInterfaceString { "org.kde.kstars" };
539 // This is only used in the constructor
540 QString ekosInterfaceString { "org.kde.kstars.Ekos" };
541 QString ekosPathString { "/KStars/Ekos" };
542
543 // the state machine holding all states
544 QSharedPointer<SchedulerModuleState> m_moduleState;
545 // process engine implementing all process steps
546 QSharedPointer<SchedulerProcess> m_process;
547
548 // react upon changes of EKOS and INDI state
549 void ekosStateChanged(EkosState state);
550 void indiStateChanged(INDIState state);
551 void indiCommunicationStatusChanged(CommunicationStatus status);
552
553 // react upon state changes
554 void startupStateChanged(StartupState state);
555 void shutdownStateChanged(ShutdownState state);
556 void parkWaitStateChanged(ParkWaitState state);
557
558 /// URL to store the scheduler file
559 QUrl schedulerURL;
560 /// URL for Ekos Sequence
561 QUrl sequenceURL;
562 /// FITS URL to solve
563 QUrl fitsURL;
564 /// Busy indicator widget
565 QProgressIndicator *pi { nullptr };
566 /// Are we editing a job right now? Job row index
567 int jobUnderEdit { -1 };
568 /// Pointer to Geographic location
569 GeoLocation *geo { nullptr };
570 /// Current target coordinates
571 SkyPoint targetCoords;
572
573 /// Call checkWeather when weatherTimer time expires. It is equal to the UpdatePeriod time in INDI::Weather device.
574 //QTimer weatherTimer;
575
576 QUrl dirPath;
577
578 // update the sleep label and its visibility
579 void changeSleepLabel(QString text, bool show = true);
580 // Used by the constructor in testing mainly so a mock ekos could be used.
581 void setupScheduler(const QString &ekosPathStr, const QString &ekosInterfaceStr);
582
583
584 /// Target coordinates for pointing check
585 QSharedPointer<SolverUtils> m_Solver;
586
587 void syncGreedyParams();
588
589 friend TestEkosSchedulerOps;
590
591 QSharedPointer<SequenceEditor> m_SequenceEditor;
592
593 QTimer m_JobUpdateDebounce;
594 QVariantMap m_Settings;
595 QVariantMap m_GlobalSettings;
596 QTimer m_DebounceTimer;
597};
598}
The SchedulerProcess class holds the entire business logic for controlling the execution of the EKOS ...
The Ekos scheduler is a simple scheduler class to orchestrate automated multi object observation jobs...
Definition scheduler.h:55
ErrorHandlingStrategy getErrorHandlingStrategy()
retrieve the error handling strategy from the UI
void moveJobUp()
moveJobUp Move the selected job up in the job list.
void watchJobChanges(bool enable)
Q_INVOKABLE void clearLog()
clearLog Clears log entry
void checkTwilightWarning(bool enabled)
checkWeather Check weather status and act accordingly depending on the current status of the schedule...
void saveJob(SchedulerJob *job=nullptr)
addToQueue Construct a SchedulerJob and add it to the queue or save job settings from current form va...
void setJobManipulation(bool can_reorder, bool can_delete, bool is_lead)
setJobManipulation Enable or disable job manipulation buttons.
void updateSchedulerURL(const QString &fileURL)
updateSchedulerURL Update scheduler URL after succesful loading a new file.
void settleSettings()
settleSettings Run this function after timeout from debounce timer to update database and emit settin...
Q_INVOKABLE void addJob(SchedulerJob *job=nullptr)
addJob Add a new job from form values
void selectSequence()
Selects sequence queue.
void insertJobTableRow(int row, bool above=true)
insertJobTableRow Insert a new row (empty) into the job table
Q_INVOKABLE bool load(bool clearQueue, const QString &filename=QString())
load Open a file dialog to select an ESL file, and load its contents.
void resumeCheckStatus()
resumeCheckStatus If the scheduler primary loop was suspended due to weather or sleep event,...
void handleSchedulerSleeping(bool shutdown, bool sleep)
handleSchedulerSleeping Update UI if scheduler is set to sleep
void prepareGUI()
prepareGUI Perform once only GUI prep processing
void moveJobDown()
moveJobDown Move the selected job down in the list.
bool importMosaic(const QJsonObject &payload)
importMosaic Import mosaic into planner and generate jobs for the scheduler.
void handleSetPaused()
handleSetPaused Update the UI when {
bool reorderJobs(QList< SchedulerJob * > reordered_sublist)
reorderJobs Change the order of jobs in the UI based on a subset of its jobs.
void syncGUIToGeneralSettings()
syncGUIToGeneralSettings set all UI fields that are not job specific
void updateNightTime(SchedulerJob const *job=nullptr)
updateNightTime update the Twilight restriction with the argument job properties.
bool loadFile(const QUrl &path)
loadFile Load scheduler jobs from disk
void handleSchedulerStateChanged(SchedulerState newState)
handleSchedulerStateChanged Update UI when the scheduler state changes
bool fillJobFromUI(SchedulerJob *job)
createJob Create a new job from form values.
Q_INVOKABLE void loadJob(QModelIndex i)
editJob Edit an observation job
void setSequence(const QString &sequenceFileURL)
Set the file URL pointing to the capture sequence file.
Q_INVOKABLE void updateJob(int index=-1)
addJob Add a new job from form values
void selectStartupScript()
Selects sequence queue.
void syncGUIToJob(SchedulerJob *job)
set all GUI fields to the values of the given scheduler job
void schedulerStopped()
schedulerStopped React when the process engine has stopped the scheduler
void selectObject()
select object from KStars's find dialog.
void updateCellStyle(SchedulerJob *job, QTableWidgetItem *cell)
Update the style of a cell, depending on the job's state.
Q_INVOKABLE void clearJobTable()
clearJobTable delete all rows in the job table
void setJobAddApply(bool add_mode)
setJobAddApply Set first button state to add new job or apply changes.
void handleConfigChanged()
handleConfigChanged Update UI after changes to the global configuration
bool saveFile(const QUrl &path)
saveFile Save scheduler jobs to disk
Q_SCRIPTABLE void sortJobsPerAltitude()
DBUS interface function.
void setErrorHandlingStrategy(ErrorHandlingStrategy strategy)
select the error handling strategy (no restart, restart after all terminated, restart immediately)
void clickQueueTable(QModelIndex index)
jobSelectionChanged Update UI state when the job list is clicked once.
void updateJobTable(SchedulerJob *job=nullptr)
updateJobTable Update the job's row in the job table.
void removeJob()
Remove a job from current table row.
void removeOneJob(int index)
Remove a job by selecting a table row.
void selectFITS()
Selects FITS file for solving.
Scheduler()
Constructor, the starndard scheduler constructor.
Definition scheduler.cpp:86
void interfaceReady(QDBusInterface *iface)
checkInterfaceReady Sometimes syncProperties() is not sufficient since the ready signal could have fi...
SchedulerColumns
Columns, in the same order as UI.
Definition scheduler.h:64
void queueTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Update scheduler parameters to the currently selected scheduler job.
void selectShutdownScript()
Selects sequence queue.
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
The QProgressIndicator class lets an application display a progress indicator to show that a long tas...
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:50
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
SchedulerJobStage
Running stages of a SchedulerJob.
ErrorHandlingStrategy
options what should happen if an error or abort occurs
Q_INVOKABLEQ_INVOKABLE
Q_OBJECTQ_OBJECT
QWidget(QWidget *parent, Qt::WindowFlags f)
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:57:24 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.