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

KDE's Doxygen guidelines are available online.