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

KDE's Doxygen guidelines are available online.