Kstars

schedulermodulestate.h
1/*
2 SPDX-FileCopyrightText: 2023 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#pragma once
8
9#include <QObject>
10#include <QProcess>
11#include "ekos/ekos.h"
12#include "indi/indiweather.h"
13#include "kstarsdatetime.h"
14#include "geolocation.h"
15#include "schedulertypes.h"
16#include <QDateTime>
17#include <QUrl>
18
19class SchedulerJob;
20
21namespace Ekos
22{
23
24class SchedulerProcess;
25class SchedulerJob;
26
27/**
28 * @class SchedulerState
29 * @brief The SchedulerState class holds all attributes defining the scheduler's state.
30 */
31class SchedulerModuleState : public QObject
32{
34
35public:
36
37
38 SchedulerModuleState();
39
40 // ////////////////////////////////////////////////////////////////////
41 // Overall scheduler state
42 // ////////////////////////////////////////////////////////////////////
43 /**
44 * @brief init Set initial conditions that need to be set before starting
45 */
46 void init();
47
48 // ////////////////////////////////////////////////////////////////////
49 // profiles and scheduler jobs
50 // ////////////////////////////////////////////////////////////////////
51
52 const QString &currentProfile() const
53 {
54 return m_currentProfile;
55 }
56 /**
57 * @brief setCurrentProfile Set the current profile name.
58 * @param newName new current profile name
59 * @param signal send an update efent if true
60 */
61 void setCurrentProfile(const QString &newName, bool signal = true);
62
63 const QStringList &profiles() const
64 {
65 return m_profiles;
66 }
67 void updateProfiles(const QStringList &newProfiles);
68
69 SchedulerJob *activeJob() const
70 {
71 return m_activeJob;
72 }
73 void setActiveJob(SchedulerJob *newActiveJob);
74
75 QList<SchedulerJob *> &mutlableJobs()
76 {
77 return m_jobs;
78 }
79 const QList<SchedulerJob *> &jobs() const
80 {
81 return m_jobs;
82 }
83
84 void setJobs(QList<SchedulerJob *> &newJobs)
85 {
86 m_jobs = newJobs;
87 }
88
89 /**
90 * @brief updateStage Helper function that updates the stage label of the active job.
91 */
92 void updateJobStage(SchedulerJobStage stage);
93
94 /**
95 * @brief getJSONJobs get jobs in JSON format
96 * @return
97 */
98 QJsonArray getJSONJobs();
99
100
101 // ////////////////////////////////////////////////////////////////////
102 // state attributes accessors
103 // ////////////////////////////////////////////////////////////////////
104
105 bool dirty() const
106 {
107 return m_dirty;
108 }
109 void setDirty(bool value)
110 {
111 m_dirty = value;
112 }
113
114 // (coarse grained) execution state of the scheduler
115 const SchedulerState &schedulerState() const
116 {
117 return m_schedulerState;
118 }
119 void setSchedulerState(const SchedulerState &newState);
120
121 const StartupState &startupState() const
122 {
123 return m_startupState;
124 }
125
126 int currentPosition() const
127 {
128 return m_currentPosition;
129 }
130 void setCurrentPosition(int newCurrentPosition);
131
132 void setStartupState(StartupState state);
133
134 const QUrl &startupScriptURL() const
135 {
136 return m_startupScriptURL;
137 }
138 void setStartupScriptURL(const QUrl &newURL)
139 {
140 m_startupScriptURL = newURL;
141 }
142
143 const ShutdownState &shutdownState() const
144 {
145 return m_shutdownState;
146 }
147 void setShutdownState(ShutdownState state);
148
149 const QUrl &shutdownScriptURL() const
150 {
151 return m_shutdownScriptURL;
152 }
153 void setShutdownScriptURL(const QUrl &newShutdownScriptURL)
154 {
155 m_shutdownScriptURL = newShutdownScriptURL;
156 }
157
158 const ParkWaitState &parkWaitState() const
159 {
160 return m_parkWaitState;
161 }
162 void setParkWaitState(ParkWaitState state);
163
164 /**
165 * @brief True if the scheduler is between iterations and delaying longer than the typical update period.
166 */
167 bool currentlySleeping()
168 {
169 return iterationTimer().isActive() && timerState() == RUN_WAKEUP;
170 }
171
172 // ////////////////////////////////////////////////////////////////////
173 // job handling
174 // ////////////////////////////////////////////////////////////////////
175
176 /**
177 * @brief removeJob Remove the job from the job list at the given position.
178 * If this is the currently active job, don't remove it and return false.
179 * @return true iff removing succeeded
180 */
181 bool removeJob(const int currentRow);
182
183
184 // ////////////////////////////////////////////////////////////////////
185 // Controls for the preemptive shutdown feature.
186 // ////////////////////////////////////////////////////////////////////
187 // Is the scheduler shutting down until later when it will resume a job?
188 void enablePreemptiveShutdown(const QDateTime &wakeupTime);
189 void disablePreemptiveShutdown();
190 const QDateTime &preemptiveShutdownWakeupTime() const;
191 bool preemptiveShutdown() const;
192
193
194 // ////////////////////////////////////////////////////////////////////
195 // overall EKOS state
196 // ////////////////////////////////////////////////////////////////////
197 EkosState ekosState() const
198 {
199 return m_ekosState;
200 }
201 void setEkosState(EkosState state);
202 // last communication result with EKOS
203 CommunicationStatus ekosCommunicationStatus() const
204 {
205 return m_EkosCommunicationStatus;
206 }
207 void setEkosCommunicationStatus(CommunicationStatus newEkosCommunicationStatus)
208 {
209 m_EkosCommunicationStatus = newEkosCommunicationStatus;
210 }
211 // counter for failed EKOS connection attempts
212 void resetEkosConnectFailureCount(uint8_t newEkosConnectFailureCount = 0)
213 {
214 m_ekosConnectFailureCount = newEkosConnectFailureCount;
215 }
216 bool increaseEkosConnectFailureCount();
217
218 void resetParkingCapFailureCount(uint8_t value = 0)
219 {
220 m_parkingCapFailureCount = value;
221 }
222 bool increaseParkingCapFailureCount();
223 void resetParkingMountFailureCount(uint8_t value = 0)
224 {
225 m_parkingMountFailureCount = value;
226 }
227 bool increaseParkingMountFailureCount();
228 uint8_t parkingMountFailureCount() const
229 {
230 return m_parkingMountFailureCount;
231 }
232 void resetParkingDomeFailureCount(uint8_t value = 0)
233 {
234 m_parkingDomeFailureCount = value;
235 }
236 bool increaseParkingDomeFailureCount();
237
238 int indexToUse() const
239 {
240 return m_IndexToUse;
241 }
242 void setIndexToUse(int newIndexToUse)
243 {
244 m_IndexToUse = newIndexToUse;
245 }
246
247 int healpixToUse() const
248 {
249 return m_HealpixToUse;
250 }
251 void setHealpixToUse(int newHealpixToUse)
252 {
253 m_HealpixToUse = newHealpixToUse;
254 }
255
256 QMap<QString, uint16_t> &capturedFramesCount()
257 {
258 return m_CapturedFramesCount;
259 }
260
261 void setCapturedFramesCount(const QMap<QString, uint16_t> &newCapturedFramesCount)
262 {
263 m_CapturedFramesCount = newCapturedFramesCount;
264 }
265
266 /**
267 * @brief resetFailureCounters Reset all failure counters
268 */
269 void resetFailureCounters();
270
271 // ////////////////////////////////////////////////////////////////////
272 // overall INDI state
273 // ////////////////////////////////////////////////////////////////////
274 INDIState indiState() const
275 {
276 return m_indiState;
277 }
278 void setIndiState(INDIState state);
279 // last communication result with INDI
280 CommunicationStatus indiCommunicationStatus() const
281 {
282 return m_INDICommunicationStatus;
283 }
284 void setIndiCommunicationStatus(CommunicationStatus newINDICommunicationStatus)
285 {
286 m_INDICommunicationStatus = newINDICommunicationStatus;
287 }
288 // counters for failed INDI connection attempts
289 void resetIndiConnectFailureCount(uint8_t newIndiConnectFailureCount = 0)
290 {
291 m_indiConnectFailureCount = newIndiConnectFailureCount;
292 }
293 bool increaseIndiConnectFailureCount();
294 /**
295 * @brief isINDIConnected Determines the status of the INDI connection.
296 * @return True if INDI connection is up and usable, else false.
297 */
298 bool isINDIConnected() const
299 {
300 return (indiCommunicationStatus() == Ekos::Success);
301 }
302 // ////////////////////////////////////////////////////////////////////
303 // device states
304 // ////////////////////////////////////////////////////////////////////
305 bool mountReady() const
306 {
307 return m_MountReady;
308 }
309 void setMountReady(bool readiness)
310 {
311 m_MountReady = readiness;
312 }
313 bool captureReady() const
314 {
315 return m_CaptureReady;
316 }
317 void setCaptureReady(bool readiness)
318 {
319 m_CaptureReady = readiness;
320 }
321 bool domeReady() const
322 {
323 return m_DomeReady;
324 }
325 void setDomeReady(bool readiness)
326 {
327 m_DomeReady = readiness;
328 }
329 bool capReady() const
330 {
331 return m_CapReady;
332 }
333 void setCapReady(bool readiness)
334 {
335 m_CapReady = readiness;
336 }
337
338 uint16_t captureBatch() const
339 {
340 return m_captureBatch;
341 }
342 void resetCaptureBatch()
343 {
344 m_captureBatch = 0;
345 }
346 uint16_t increaseCaptureBatch()
347 {
348 return m_captureBatch++;
349 }
350
351 uint8_t captureFailureCount() const
352 {
353 return m_captureFailureCount;
354 }
355 void resetCaptureFailureCount()
356 {
357 m_captureFailureCount = 0;
358 }
359 bool increaseCaptureFailureCount();
360
361 uint8_t focusFailureCount() const
362 {
363 return m_focusFailureCount;
364 }
365 void resetFocusFailureCount()
366 {
367 m_focusFailureCount = 0;
368 }
369 bool increaseFocusFailureCount();
370
371 bool autofocusCompleted() const
372 {
373 return m_autofocusCompleted;
374 }
375 void setAutofocusCompleted(bool value)
376 {
377 m_autofocusCompleted = value;
378 }
379
380 uint8_t guideFailureCount() const
381 {
382 return m_guideFailureCount;
383 }
384 void resetGuideFailureCount()
385 {
386 m_guideFailureCount = 0;
387 }
388 bool increaseGuideFailureCount();
389
390 uint8_t alignFailureCount() const
391 {
392 return m_alignFailureCount;
393 }
394 void resetAlignFailureCount()
395 {
396 m_alignFailureCount = 0;
397 }
398 bool increaseAlignFailureCount();
399
400 int restartGuidingInterval() const
401 {
402 return m_restartGuidingInterval;
403 }
404
405 const KStarsDateTime &restartGuidingTime() const
406 {
407 return m_restartGuidingTime;
408 }
409
410 ISD::Weather::Status weatherStatus() const
411 {
412 return m_weatherStatus;
413 }
414 void setWeatherStatus(ISD::Weather::Status newWeatherStatus)
415 {
416 m_weatherStatus = newWeatherStatus;
417 }
418
419 // ////////////////////////////////////////////////////////////////////
420 // Timers and time
421 // ////////////////////////////////////////////////////////////////////
422 // Returns milliseconds since startCurrentOperationTImer() was called.
423 qint64 getCurrentOperationMsec() const;
424 // Starts the above operation timer.
425 // TODO. It would be better to make this a class and give each operation its own timer.
426 // TODO. These should be disabled once no longer relevant.
427 // These are implement with a KStarsDateTime instead of a QTimer type class
428 // so that the simulated clock can be used.
429 void startCurrentOperationTimer();
430
431 // Controls for the guiding timer, which restarts guiding after failure.
432 void cancelGuidingTimer();
433 bool isGuidingTimerActive();
434 void startGuidingTimer(int milliseconds);
435
436 /** @brief Setter used in testing to fix the local time. Otherwise getter gets from KStars instance. */
437 /** @{ */
438 static KStarsDateTime getLocalTime();
439 static void setLocalTime(KStarsDateTime *time)
440 {
441 storedLocalTime = time;
442 }
443 static bool hasLocalTime()
444 {
445 return storedLocalTime != nullptr;
446 }
447
448 /** @} */
449
450
451 // ////////////////////////////////////////////////////////////////////
452 // Astronomical calculations
453 // ////////////////////////////////////////////////////////////////////
454 /**
455 * @brief calculateDawnDusk find the next astronomical dawn and dusk after the current date and time of observation
456 */
457 static void calculateDawnDusk(QDateTime const &when, QDateTime &nDawn, QDateTime &nDusk);
458
459 /**
460 * @brief calculateDawnDusk Calculate dawn and dusk times for today
461 */
462 void calculateDawnDusk();
463
464 static QDateTime Dawn()
465 {
466 return m_Dawn;
467 }
468 static QDateTime Dusk()
469 {
470 return m_Dusk;
471 }
472 static QDateTime PreDawnDateTime()
473 {
474 return m_PreDawnDateTime;
475 }
476
477 /** @brief Setter used in testing to fix the geo location. Otherwise getter gets from KStars instance. */
478 /** @{ */
479 static const GeoLocation *getGeo();
480 static void setGeo(GeoLocation *geo)
481 {
482 storedGeo = geo;
483 }
484 static bool hasGeo();
485
486 // ////////////////////////////////////////////////////////////////////
487 // Scheduler iterations
488 // ////////////////////////////////////////////////////////////////////
489
490 // Setup the parameters for the next scheduler iteration.
491 // When milliseconds is not passed in, it uses m_UpdatePeriodMs.
492 void setupNextIteration(SchedulerTimerState nextState);
493 void setupNextIteration(SchedulerTimerState nextState, int milliseconds);
494
495 SchedulerTimerState timerState() const
496 {
497 return m_timerState;
498 }
499
500 void setTimerState(SchedulerTimerState newTimerState)
501 {
502 m_timerState = newTimerState;
503 }
504
505 QTimer &iterationTimer()
506 {
507 return m_iterationTimer;
508 }
509
510 bool iterationSetup() const
511 {
512 return m_iterationSetup;
513 }
514 void setIterationSetup(bool setup)
515 {
516 m_iterationSetup = setup;
517 }
518
519 qint64 startMSecs() const
520 {
521 return m_startMSecs;
522 }
523 void setStartMSecs(qint64 value)
524 {
525 m_startMSecs = value;
526 }
527 int increaseSchedulerIteration()
528 {
529 return ++m_schedulerIteration;
530 }
531 void resetSchedulerIteration()
532 {
533 m_schedulerIteration = 0;
534 }
535
536 int timerInterval() const
537 {
538 return m_timerInterval;
539 }
540 void setTimerInterval(int value)
541 {
542 m_timerInterval = value;
543 }
544
545 void setUpdatePeriodMs(int ms)
546 {
547 m_UpdatePeriodMs = ms;
548 }
549 int updatePeriodMs() const
550 {
551 return m_UpdatePeriodMs;
552 }
553
554 uint sequenceExecutionCounter() const
555 {
556 return m_sequenceExecutionCounter;
557 }
558 void resetSequenceExecutionCounter()
559 {
560 m_sequenceExecutionCounter = 1;
561 }
562 void increaseSequenceExecutionCounter()
563 {
564 m_sequenceExecutionCounter++;
565 }
566
567 static uint maxFailureAttempts();
568
569 QStringList &logText()
570 {
571 return m_logText;
572 }
573 QString getLogText()
574 {
575 return logText().join("\n");
576 }
577 void clearLog();
578
579 /**
580 * @brief checkRepeatSequence Check if the entire job sequence might be repeated
581 * @return true if the checkbox is set and the number of iterations is below the
582 * configured threshold
583 */
584 bool checkRepeatSequence();
585
586 void resetSolverIteration()
587 {
588 m_solverIteration = 0;
589 }
590 uint32_t increaseSolverIteration()
591 {
592 return ++m_solverIteration;
593 }
594
595signals:
596 // ////////////////////////////////////////////////////////////////////
597 // communication with the UI
598 // ////////////////////////////////////////////////////////////////////
599 // State change of EKOS
600 void ekosStateChanged(EkosState state);
601 // State change of INDI
602 void indiStateChanged(INDIState state);
603 // overall scheduler state changed
604 void schedulerStateChanged(SchedulerState state);
605 // startup state
606 void startupStateChanged(StartupState state);
607 // shutdown state
608 void shutdownStateChanged(ShutdownState state);
609 // parking state
610 void parkWaitStateChanged(ParkWaitState state);
611 // profiles updated
612 void profilesChanged();
613 // current profile changed
614 void currentProfileChanged();
615 // new log text for the module log window
616 void newLog(const QString &text);
617 // current position in the job list changed
618 void currentPositionChanged(int pos);
619 // job stage of the current job changed
620 void jobStageChanged(SchedulerJobStage stage);
621 // night time calculation updated
622 void updateNightTime(SchedulerJob const * job = nullptr);
623
624
625private:
626 // ////////////////////////////////////////////////////////////////////
627 // Scheduler jobs
628 // ////////////////////////////////////////////////////////////////////
629 // List of all jobs as entered by the user or file
631 // Active job
632 SchedulerJob *m_activeJob { nullptr };
633
634 // ////////////////////////////////////////////////////////////////////
635 // state attributes
636 // ////////////////////////////////////////////////////////////////////
637 // coarse grained state describing the general execution state
638 SchedulerState m_schedulerState { SCHEDULER_IDLE };
639 // states of the scheduler startup
640 StartupState m_startupState { STARTUP_IDLE };
641 // Startup script URL
642 QUrl m_startupScriptURL;
643 // states of the scheduler shutdown
644 ShutdownState m_shutdownState { SHUTDOWN_IDLE };
645 // current position on the job list - necessary if there is no line selected in the
646 // UI, for example after deleting a row.
647 int m_currentPosition { -1 };
648 // Shutdown script URL
649 QUrl m_shutdownScriptURL;
650 // states of parking
651 ParkWaitState m_parkWaitState { PARKWAIT_IDLE };
652 // current profile
653 QString m_currentProfile;
654 // all profiles
655 QStringList m_profiles;
656 /// Store all log strings
657 QStringList m_logText;
658 // Was job modified and needs saving?
659 bool m_dirty { false };
660
661 // EKOS state describing whether EKOS is running (remember that the scheduler
662 // does not need EKOS running).
663 EkosState m_ekosState { EKOS_IDLE };
664 // Execution state of INDI
665 INDIState m_indiState { INDI_IDLE };
666 // Last communication result with EKOS and INDI
667 CommunicationStatus m_EkosCommunicationStatus { Ekos::Idle };
668 CommunicationStatus m_INDICommunicationStatus { Ekos::Idle };
669
670 // device readiness
671 bool m_MountReady { false };
672 bool m_CaptureReady { false };
673 bool m_DomeReady { false };
674 bool m_CapReady { false };
675
676 // Restricts (the internal solver) to using the index and healpix
677 // from the previous solve, if that solve was successful, when
678 // doing the pointing check. -1 means no restriction.
679 int m_IndexToUse { -1 };
680 int m_HealpixToUse { -1 };
681
682 // Check if initial autofocus is completed and do not run autofocus until
683 // there is a change is telescope position/alignment.
684 bool m_autofocusCompleted { false };
685
686 // Used when solving position every nth capture.
687 uint32_t m_solverIteration {0};
688
689
690 // Keep watch of weather status
691 ISD::Weather::Status m_weatherStatus { ISD::Weather::WEATHER_IDLE };
692
693 // ////////////////////////////////////////////////////////////////////
694 // counters
695 // ////////////////////////////////////////////////////////////////////
696 // count for job sequence iteration
697 uint m_sequenceExecutionCounter { 1 };
698 // Keep track of INDI connection failures
699 uint8_t m_indiConnectFailureCount { 0 };
700 // Keep track of Ekos connection failures
701 uint8_t m_ekosConnectFailureCount { 0 };
702 // failures parking dust cap
703 uint8_t m_parkingCapFailureCount { 0 };
704 // failures parking mount
705 uint8_t m_parkingMountFailureCount { 0 };
706 // failures parking dome
707 uint8_t m_parkingDomeFailureCount { 0 };
708 // How many repeated job batches did we complete thus far?
709 uint16_t m_captureBatch { 0 };
710 // Keep track of Ekos capture module failures
711 uint8_t m_captureFailureCount { 0 };
712 // Keep track of Ekos focus module failures
713 uint8_t m_focusFailureCount { 0 };
714 // Keep track of Ekos guide module failures
715 uint8_t m_guideFailureCount { 0 };
716 // Keep track of Ekos align module failures
717 uint8_t m_alignFailureCount { 0 };
718 // frames count for all signatures
719 QMap<QString, uint16_t> m_CapturedFramesCount;
720
721 // ////////////////////////////////////////////////////////////////////
722 // Scheduler iterations
723 // ////////////////////////////////////////////////////////////////////
724
725 // The type of scheduler iteration that should be run next.
726 SchedulerTimerState m_timerState { RUN_NOTHING };
727 // Variable keeping the number of millisconds the scheduler should wait
728 // after the current scheduler iteration.
729 int m_timerInterval { -1 };
730 // Whether the scheduler has been setup for the next iteration,
731 // that is, whether timerInterval and timerState have been set this iteration.
732 bool m_iterationSetup { false };
733 // The timer used to wakeup the scheduler between iterations.
734 QTimer m_iterationTimer;
735 // Counter for how many scheduler iterations have been processed.
736 int m_schedulerIteration { 0 };
737 // The time when the scheduler first started running iterations.
738 qint64 m_startMSecs { 0 };
739 // This is the time between typical scheduler iterations.
740 // The time can be modified for testing.
741 int m_UpdatePeriodMs = 1000;
742
743 // ////////////////////////////////////////////////////////////////////
744 // time and timers
745 // ////////////////////////////////////////////////////////////////////
746 // constants for current dawn and dusk
747 /// Store next dawn to calculate dark skies range
748 static QDateTime m_Dawn;
749 /// Store next dusk to calculate dark skies range
750 static QDateTime m_Dusk;
751 /// Pre-dawn is where we stop all jobs, it is a user-configurable value before Dawn.
752 static QDateTime m_PreDawnDateTime;
753 // Generic time to track timeout of current operation in progress.
754 // Used by startCurrentOperationTimer() and getCurrentOperationMsec().
755 KStarsDateTime currentOperationTime;
756 bool currentOperationTimeStarted { false };
757 // Delay for restarting the guider
758 int m_restartGuidingInterval { -1 };
759 KStarsDateTime m_restartGuidingTime;
760 // Used in testing, instead of KStars::Instance() resources
761 static KStarsDateTime *storedLocalTime;
762 // The various preemptiveShutdown states are controlled by this one variable.
763 QDateTime m_preemptiveShutdownWakeupTime;
764
765 // These are used in testing, instead of KStars::Instance() resources
766 static GeoLocation *storedGeo;
767
768};
769} // Ekos namespace
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
The SchedulerState class holds all attributes defining the scheduler's state.
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:79
Q_OBJECTQ_OBJECT
QString join(QChar separator) const const
bool isActive() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:49:51 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.