6#include "schedulermodulestate.h"
7#include "schedulerjob.h"
8#include <ekos_scheduler_debug.h>
9#include "schedulerprocess.h"
10#include "schedulerjob.h"
11#include "kstarsdata.h"
15#define MAX_FAILURE_ATTEMPTS 5
20QDateTime SchedulerModuleState::m_Dawn, SchedulerModuleState::m_Dusk, SchedulerModuleState::m_PreDawnDateTime;
21GeoLocation *SchedulerModuleState::storedGeo =
nullptr;
23SchedulerModuleState::SchedulerModuleState() {}
25void SchedulerModuleState::init()
30 enablePreemptiveShutdown(SchedulerModuleState::getLocalTime());
32 setIterationSetup(
false);
33 setupNextIteration(RUN_WAKEUP, 10);
36void SchedulerModuleState::setCurrentProfile(
const QString &newName,
bool signal)
38 bool changed = (newName != m_currentProfile);
40 if (m_profiles.contains(newName))
41 m_currentProfile = newName;
44 changed = (m_currentProfile != m_profiles.first());
45 m_currentProfile = m_profiles.first();
48 if (signal && changed)
49 emit currentProfileChanged();
52void SchedulerModuleState::updateProfiles(
const QStringList &newProfiles)
54 QString selected = currentProfile();
56 QStringList allProfiles(
i18n(
"Default"));
57 allProfiles.append(newProfiles);
59 m_profiles = allProfiles;
61 setCurrentProfile(selected,
false);
62 emit profilesChanged();
65SchedulerJob *SchedulerModuleState::activeJob(
const QString &trainname)
const
68 if (trainname ==
"" || m_activeJob ==
nullptr || (m_activeJob !=
nullptr && m_activeJob->getOpticalTrain() == trainname))
72 foreach (
auto follower, m_activeJob->followerJobs())
74 if (follower->getOpticalTrain() == trainname)
83void SchedulerModuleState::setActiveJob(SchedulerJob *newActiveJob)
85 m_activeJob = newActiveJob;
88QList<SchedulerJob *> SchedulerModuleState::leadJobs()
90 QList<SchedulerJob *> result;
91 for (
auto job : jobs())
98QList<SchedulerJob *> SchedulerModuleState::followerJobs()
100 QList<SchedulerJob *> result;
101 for (
auto job : jobs())
110 if (activeJob() ==
nullptr)
112 emit jobStageChanged(SCHEDSTAGE_IDLE);
116 activeJob()->setStage(stage);
117 emit jobStageChanged(stage);
121QJsonArray SchedulerModuleState::getJSONJobs()
125 for (
const auto &oneJob : jobs())
126 jobArray.
append(oneJob->toJson());
131void SchedulerModuleState::setSchedulerState(
const SchedulerState &newState)
133 m_schedulerState = newState;
134 emit schedulerStateChanged(newState);
137void SchedulerModuleState::setCurrentPosition(
int newCurrentPosition)
139 m_currentPosition = newCurrentPosition;
140 emit currentPositionChanged(newCurrentPosition);
143void SchedulerModuleState::setStartupState(StartupState state)
145 if (m_startupState != state)
147 m_startupState = state;
148 emit startupStateChanged(state);
152void SchedulerModuleState::setShutdownState(ShutdownState state)
154 if (m_shutdownState != state)
156 m_shutdownState = state;
157 emit shutdownStateChanged(state);
161void SchedulerModuleState::setParkWaitState(ParkWaitState state)
163 if (m_parkWaitState != state)
165 m_parkWaitState = state;
166 emit parkWaitStateChanged(state);
170bool SchedulerModuleState::removeJob(
const int currentRow)
177 SchedulerJob *
const job = jobs().at(currentRow);
180 if (job == m_activeJob)
182 emit newLog(
i18n(
"Cannot delete currently running job '%1'.", job->getName()));
185 else if (job ==
nullptr || (activeJob() ==
nullptr && schedulerState() != SCHEDULER_IDLE))
188 emit newLog(
i18n(
"Cannot delete job. Scheduler state: %1",
189 getSchedulerStatusString(schedulerState(),
true)));
193 qCDebug(KSTARS_EKOS_SCHEDULER) << QString(
"Job '%1' at row #%2 is being deleted.").arg(job->getName()).arg(currentRow + 1);
196 if (job->isLead() && job->followerJobs().count() > 0)
199 SchedulerJob *newLead = findLead(currentRow - 1);
201 if (newLead ==
nullptr)
208 for (
auto follower : job->followerJobs())
210 follower->setLeadJob(newLead);
211 newLead->followerJobs().append(follower);
216 mutlableJobs().removeOne(job);
221 if (currentPosition() >= jobs().count())
222 setCurrentPosition(jobs().count() - 1);
229void SchedulerModuleState::refreshFollowerLists()
232 for (
auto job : m_jobs)
233 job->followerJobs().clear();
236 for (
auto job : m_jobs)
238 SchedulerJob *lead = job->leadJob();
239 if (job->isLead() ==
false && lead !=
nullptr)
241 lead->followerJobs().append(job);
242 lead->updateSharedFollowerAttributes();
247SchedulerJob *SchedulerModuleState::findLead(
int position,
bool upward)
249 auto start = std::min(position,
static_cast<int>(jobs().count()));
253 for (
int i = start; i >= 0; i--)
254 if (jobs().at(i)->isLead())
259 for (
int i = start; i < jobs().count(); i++)
260 if (jobs().at(i)->isLead())
268void SchedulerModuleState::enablePreemptiveShutdown(
const QDateTime &wakeupTime)
270 m_preemptiveShutdownWakeupTime = wakeupTime;
273void SchedulerModuleState::disablePreemptiveShutdown()
275 m_preemptiveShutdownWakeupTime = QDateTime();
278const QDateTime &SchedulerModuleState::preemptiveShutdownWakeupTime()
const
280 return m_preemptiveShutdownWakeupTime;
283bool SchedulerModuleState::preemptiveShutdown()
const
285 return m_preemptiveShutdownWakeupTime.isValid();
288void SchedulerModuleState::setEkosState(EkosState state)
290 if (m_ekosState != state)
292 qCDebug(KSTARS_EKOS_SCHEDULER) <<
"EKOS state changed from" << m_ekosState <<
"to" << state;
294 emit ekosStateChanged(state);
298bool SchedulerModuleState::increaseEkosConnectFailureCount()
300 return (++m_ekosConnectFailureCount <= MAX_FAILURE_ATTEMPTS);
303bool SchedulerModuleState::increaseParkingCapFailureCount()
305 return (++m_parkingCapFailureCount <= MAX_FAILURE_ATTEMPTS);
308bool SchedulerModuleState::increaseParkingMountFailureCount()
310 return (++m_parkingMountFailureCount <= MAX_FAILURE_ATTEMPTS);
313bool SchedulerModuleState::increaseParkingDomeFailureCount()
315 return (++m_parkingDomeFailureCount <= MAX_FAILURE_ATTEMPTS);
318void SchedulerModuleState::resetFailureCounters()
320 resetIndiConnectFailureCount();
321 resetEkosConnectFailureCount();
322 resetFocusFailureCount();
323 resetGuideFailureCount();
324 resetAlignFailureCount();
325 resetCaptureFailureCount();
328bool SchedulerModuleState::increaseIndiConnectFailureCount()
330 return (++m_indiConnectFailureCount <= MAX_FAILURE_ATTEMPTS);
333bool SchedulerModuleState::increaseCaptureFailureCount()
335 return (++m_captureFailureCount <= MAX_FAILURE_ATTEMPTS);
338bool SchedulerModuleState::increaseFocusFailureCount(
const QString &trainname)
340 return (++m_focusFailureCount[trainname] <= MAX_FAILURE_ATTEMPTS);
343bool SchedulerModuleState::increaseAllFocusFailureCounts()
348 for (QMap<QString, bool>::const_iterator it = m_autofocusCompleted.cbegin(); it != m_autofocusCompleted.cend(); it++)
349 result &= increaseFocusFailureCount(it.key());
354bool SchedulerModuleState::autofocusCompleted(
const QString &trainname)
const
357 return m_autofocusCompleted[trainname];
359 return autofocusCompleted();
362void SchedulerModuleState::setAutofocusCompleted(
const QString &trainname,
bool value)
365 m_autofocusCompleted[trainname] = value;
367 m_autofocusCompleted.clear();
370bool SchedulerModuleState::autofocusCompleted()
const
372 if (m_autofocusCompleted.isEmpty())
375 for (QMap<QString, bool>::const_iterator it = m_autofocusCompleted.cbegin(); it != m_autofocusCompleted.cend(); it++)
377 if (it.value() ==
false)
384bool SchedulerModuleState::increaseGuideFailureCount()
386 return (++m_guideFailureCount <= MAX_FAILURE_ATTEMPTS);
389bool SchedulerModuleState::increaseAlignFailureCount()
391 return (++m_alignFailureCount <= MAX_FAILURE_ATTEMPTS);
394void SchedulerModuleState::setIndiState(INDIState state)
396 if (m_indiState != state)
398 qCDebug(KSTARS_EKOS_SCHEDULER) <<
"INDI state changed from" << m_indiState <<
"to" << state;
400 emit indiStateChanged(state);
404qint64 SchedulerModuleState::getCurrentOperationMsec()
const
406 if (!currentOperationTimeStarted)
return 0;
407 return currentOperationTime.msecsTo(KStarsData::Instance()->ut());
410void SchedulerModuleState::startCurrentOperationTimer()
412 currentOperationTimeStarted =
true;
413 currentOperationTime = KStarsData::Instance()->
ut();
416void SchedulerModuleState::cancelGuidingTimer()
418 m_restartGuidingInterval = -1;
419 m_restartGuidingTime = KStarsDateTime();
422bool SchedulerModuleState::isGuidingTimerActive()
424 return (m_restartGuidingInterval > 0 &&
425 m_restartGuidingTime.msecsTo(KStarsData::Instance()->ut()) >= 0);
428void SchedulerModuleState::startGuidingTimer(
int milliseconds)
430 m_restartGuidingInterval = milliseconds;
431 m_restartGuidingTime = KStarsData::Instance()->
ut();
436KStarsDateTime *SchedulerModuleState::storedLocalTime =
nullptr;
437KStarsDateTime SchedulerModuleState::getLocalTime()
440 return *storedLocalTime;
441 return KStarsData::Instance()->
geo()->UTtoLT(KStarsData::Instance()->clock()->utc());
444void SchedulerModuleState::calculateDawnDusk(
const QDateTime &when, QDateTime &nDawn, QDateTime &nDusk)
446 QDateTime startup = when;
449 startup = getLocalTime();
455 QDateTime dawn = startup, dusk = startup;
458 for ( ; dawn <= startup || dusk <= startup ; midnight = midnight.
addDays(1))
463 KSAlmanac
const ksal(midnight, getGeo());
466 dawn = getGeo()->UTtoLT(ksal.getDate().addSecs((ksal.getDawnAstronomicalTwilight() * 24.0 + Options::dawnOffset()) *
470 dusk = getGeo()->UTtoLT(ksal.getDate().addSecs((ksal.getDuskAstronomicalTwilight() * 24.0 + Options::duskOffset()) *
474 static QMap<QString, KSAlmanac const * > almanacMap;
475 const QString key = QString(
"%1 %2 %3").arg(midnight.toString()).arg(getGeo()->lat()->Degrees()).arg(
476 getGeo()->lng()->Degrees());
477 KSAlmanac
const * ksal = almanacMap.
value(key,
nullptr);
480 if (almanacMap.
size() > 5)
483 qDeleteAll(almanacMap);
486 ksal =
new KSAlmanac(midnight, getGeo());
487 almanacMap[key] = ksal;
492 dawn = getGeo()->UTtoLT(ksal->getDate().
addSecs((ksal->getDawnAstronomicalTwilight() * 24.0 + Options::dawnOffset()) *
497 dusk = getGeo()->UTtoLT(ksal->getDate().
addSecs((ksal->getDuskAstronomicalTwilight() * 24.0 + Options::duskOffset()) *
509void SchedulerModuleState::calculateDawnDusk()
511 calculateDawnDusk(QDateTime(), m_Dawn, m_Dusk);
513 m_PreDawnDateTime = m_Dawn.addSecs(-60.0 * abs(Options::preDawnTime()));
514 emit updateNightTime();
517const GeoLocation *SchedulerModuleState::getGeo()
521 return KStarsData::Instance()->
geo();
524bool SchedulerModuleState::hasGeo()
526 return storedGeo !=
nullptr;
531 setupNextIteration(nextState, m_UpdatePeriodMs);
534void SchedulerModuleState::setupNextIteration(
SchedulerTimerState nextState,
int milliseconds)
536 if (iterationSetup())
538 qCDebug(KSTARS_EKOS_SCHEDULER)
539 << QString(
"Multiple setupNextIteration calls: current %1 %2, previous %3 %4")
540 .arg(nextState).arg(milliseconds).arg(timerState()).arg(timerInterval());
542 setTimerState(nextState);
544 if (iterationTimer().isActive())
547 int remaining = iterationTimer().remainingTime();
548 iterationTimer().stop();
549 setTimerInterval(std::max(0, milliseconds - remaining));
550 iterationTimer().start(timerInterval());
555 setTimerInterval(milliseconds);
557 tickleTimer().stop();
558 setIterationSetup(
true);
561uint SchedulerModuleState::maxFailureAttempts()
563 return MAX_FAILURE_ATTEMPTS;
566void SchedulerModuleState::clearLog()
569 emit newLog(QString());
572bool SchedulerModuleState::checkRepeatSequence()
574 return (!Options::rememberJobProgress() && Options::schedulerRepeatEverything() &&
575 (Options::schedulerExecutionSequencesLimit() == 0
576 || sequenceExecutionCounter()) < Options::schedulerExecutionSequencesLimit());
const KStarsDateTime & ut() const
KStarsDateTime addSecs(double s) const
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
SchedulerJobStage
Running stages of a SchedulerJob.
SchedulerTimerState
IterationTypes, the different types of scheduler iterations that are run.
QDateTime addDays(qint64 ndays) const const
bool isValid() const const
void append(const QJsonValue &value)
void append(QList< T > &&value)
size_type size() const const
T value(const Key &key, const T &defaultValue) const const
bool isEmpty() const const