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

KDE's Doxygen guidelines are available online.