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();
65void SchedulerModuleState::setActiveJob(SchedulerJob *newActiveJob)
67 m_activeJob = newActiveJob;
70QList<SchedulerJob *> SchedulerModuleState::leadJobs()
72 QList<SchedulerJob *> result;
73 for (
auto job : jobs())
80QList<SchedulerJob *> SchedulerModuleState::followerJobs()
82 QList<SchedulerJob *> result;
83 for (
auto job : jobs())
92 if (activeJob() ==
nullptr)
94 emit jobStageChanged(SCHEDSTAGE_IDLE);
98 activeJob()->setStage(stage);
99 emit jobStageChanged(stage);
103QJsonArray SchedulerModuleState::getJSONJobs()
107 for (
const auto &oneJob : jobs())
108 jobArray.
append(oneJob->toJson());
113void SchedulerModuleState::setSchedulerState(
const SchedulerState &newState)
115 m_schedulerState = newState;
116 emit schedulerStateChanged(newState);
119void SchedulerModuleState::setCurrentPosition(
int newCurrentPosition)
121 m_currentPosition = newCurrentPosition;
122 emit currentPositionChanged(newCurrentPosition);
125void SchedulerModuleState::setStartupState(StartupState state)
127 if (m_startupState != state)
129 m_startupState = state;
130 emit startupStateChanged(state);
134void SchedulerModuleState::setShutdownState(ShutdownState state)
136 if (m_shutdownState != state)
138 m_shutdownState = state;
139 emit shutdownStateChanged(state);
143void SchedulerModuleState::setParkWaitState(ParkWaitState state)
145 if (m_parkWaitState != state)
147 m_parkWaitState = state;
148 emit parkWaitStateChanged(state);
152bool SchedulerModuleState::removeJob(
const int currentRow)
159 SchedulerJob *
const job = jobs().at(currentRow);
162 if (job == m_activeJob)
164 emit newLog(
i18n(
"Cannot delete currently running job '%1'.", job->getName()));
167 else if (job ==
nullptr || (activeJob() ==
nullptr && schedulerState() != SCHEDULER_IDLE))
170 emit newLog(
i18n(
"Cannot delete job. Scheduler state: %1",
171 getSchedulerStatusString(schedulerState(),
true)));
175 qCDebug(KSTARS_EKOS_SCHEDULER) << QString(
"Job '%1' at row #%2 is being deleted.").arg(job->getName()).arg(currentRow + 1);
178 if (job->isLead() && job->followerJobs().count() > 0)
181 SchedulerJob *newLead = findLead(currentRow - 1);
183 if (newLead ==
nullptr)
190 for (
auto follower : job->followerJobs())
192 follower->setLeadJob(newLead);
193 newLead->followerJobs().append(follower);
198 mutlableJobs().removeOne(job);
203 if (currentPosition() >= jobs().count())
204 setCurrentPosition(jobs().count() - 1);
211void SchedulerModuleState::refreshFollowerLists()
214 for (
auto job : m_jobs)
215 job->followerJobs().clear();
218 for (
auto job : m_jobs)
220 SchedulerJob *lead = job->leadJob();
221 if (job->isLead() ==
false && lead !=
nullptr)
223 lead->followerJobs().append(job);
224 lead->updateSharedFollowerAttributes();
229SchedulerJob *SchedulerModuleState::findLead(
int position,
bool upward)
231 auto start = std::min(position,
static_cast<int>(jobs().count()));
235 for (
int i = start; i >= 0; i--)
236 if (jobs().at(i)->isLead())
241 for (
int i = start; i < jobs().count(); i++)
242 if (jobs().at(i)->isLead())
250void SchedulerModuleState::enablePreemptiveShutdown(
const QDateTime &wakeupTime)
252 m_preemptiveShutdownWakeupTime = wakeupTime;
255void SchedulerModuleState::disablePreemptiveShutdown()
257 m_preemptiveShutdownWakeupTime = QDateTime();
260const QDateTime &SchedulerModuleState::preemptiveShutdownWakeupTime()
const
262 return m_preemptiveShutdownWakeupTime;
265bool SchedulerModuleState::preemptiveShutdown()
const
267 return m_preemptiveShutdownWakeupTime.isValid();
270void SchedulerModuleState::setEkosState(EkosState state)
272 if (m_ekosState != state)
274 qCDebug(KSTARS_EKOS_SCHEDULER) <<
"EKOS state changed from" << m_ekosState <<
"to" << state;
276 emit ekosStateChanged(state);
280bool SchedulerModuleState::increaseEkosConnectFailureCount()
282 return (++m_ekosConnectFailureCount <= MAX_FAILURE_ATTEMPTS);
285bool SchedulerModuleState::increaseParkingCapFailureCount()
287 return (++m_parkingCapFailureCount <= MAX_FAILURE_ATTEMPTS);
290bool SchedulerModuleState::increaseParkingMountFailureCount()
292 return (++m_parkingMountFailureCount <= MAX_FAILURE_ATTEMPTS);
295bool SchedulerModuleState::increaseParkingDomeFailureCount()
297 return (++m_parkingDomeFailureCount <= MAX_FAILURE_ATTEMPTS);
300void SchedulerModuleState::resetFailureCounters()
302 resetIndiConnectFailureCount();
303 resetEkosConnectFailureCount();
304 resetFocusFailureCount();
305 resetGuideFailureCount();
306 resetAlignFailureCount();
307 resetCaptureFailureCount();
310bool SchedulerModuleState::increaseIndiConnectFailureCount()
312 return (++m_indiConnectFailureCount <= MAX_FAILURE_ATTEMPTS);
315bool SchedulerModuleState::increaseCaptureFailureCount()
317 return (++m_captureFailureCount <= MAX_FAILURE_ATTEMPTS);
320bool SchedulerModuleState::increaseFocusFailureCount(
const QString &trainname)
322 return (++m_focusFailureCount[trainname] <= MAX_FAILURE_ATTEMPTS);
325bool SchedulerModuleState::increaseAllFocusFailureCounts()
330 for (QMap<QString, bool>::const_iterator it = m_autofocusCompleted.cbegin(); it != m_autofocusCompleted.cend(); it++)
331 result &= increaseFocusFailureCount(it.key());
336bool SchedulerModuleState::autofocusCompleted(
const QString &trainname)
const
339 return m_autofocusCompleted[trainname];
341 return autofocusCompleted();
344void SchedulerModuleState::setAutofocusCompleted(
const QString &trainname,
bool value)
347 m_autofocusCompleted[trainname] = value;
349 m_autofocusCompleted.clear();
352bool SchedulerModuleState::autofocusCompleted()
const
354 if (m_autofocusCompleted.isEmpty())
357 for (QMap<QString, bool>::const_iterator it = m_autofocusCompleted.cbegin(); it != m_autofocusCompleted.cend(); it++)
359 if (it.value() ==
false)
366bool SchedulerModuleState::increaseGuideFailureCount()
368 return (++m_guideFailureCount <= MAX_FAILURE_ATTEMPTS);
371bool SchedulerModuleState::increaseAlignFailureCount()
373 return (++m_alignFailureCount <= MAX_FAILURE_ATTEMPTS);
376void SchedulerModuleState::setIndiState(INDIState state)
378 if (m_indiState != state)
380 qCDebug(KSTARS_EKOS_SCHEDULER) <<
"INDI state changed from" << m_indiState <<
"to" << state;
382 emit indiStateChanged(state);
386qint64 SchedulerModuleState::getCurrentOperationMsec()
const
388 if (!currentOperationTimeStarted)
return 0;
389 return currentOperationTime.msecsTo(KStarsData::Instance()->ut());
392void SchedulerModuleState::startCurrentOperationTimer()
394 currentOperationTimeStarted =
true;
395 currentOperationTime = KStarsData::Instance()->
ut();
398void SchedulerModuleState::cancelGuidingTimer()
400 m_restartGuidingInterval = -1;
401 m_restartGuidingTime = KStarsDateTime();
404bool SchedulerModuleState::isGuidingTimerActive()
406 return (m_restartGuidingInterval > 0 &&
407 m_restartGuidingTime.msecsTo(KStarsData::Instance()->ut()) >= 0);
410void SchedulerModuleState::startGuidingTimer(
int milliseconds)
412 m_restartGuidingInterval = milliseconds;
413 m_restartGuidingTime = KStarsData::Instance()->
ut();
418KStarsDateTime *SchedulerModuleState::storedLocalTime =
nullptr;
419KStarsDateTime SchedulerModuleState::getLocalTime()
422 return *storedLocalTime;
423 return KStarsData::Instance()->
geo()->UTtoLT(KStarsData::Instance()->clock()->utc());
426void SchedulerModuleState::calculateDawnDusk(
const QDateTime &when, QDateTime &nDawn, QDateTime &nDusk)
428 QDateTime startup = when;
431 startup = getLocalTime();
437 QDateTime dawn = startup, dusk = startup;
440 for ( ; dawn <= startup || dusk <= startup ; midnight = midnight.
addDays(1))
445 KSAlmanac
const ksal(midnight, getGeo());
448 dawn = getGeo()->UTtoLT(ksal.getDate().addSecs((ksal.getDawnAstronomicalTwilight() * 24.0 + Options::dawnOffset()) *
452 dusk = getGeo()->UTtoLT(ksal.getDate().addSecs((ksal.getDuskAstronomicalTwilight() * 24.0 + Options::duskOffset()) *
456 static QMap<QString, KSAlmanac const * > almanacMap;
457 const QString key = QString(
"%1 %2 %3").arg(midnight.toString()).arg(getGeo()->lat()->Degrees()).arg(
458 getGeo()->lng()->Degrees());
459 KSAlmanac
const * ksal = almanacMap.
value(key,
nullptr);
462 if (almanacMap.
size() > 5)
465 qDeleteAll(almanacMap);
468 ksal =
new KSAlmanac(midnight, getGeo());
469 almanacMap[key] = ksal;
474 dawn = getGeo()->UTtoLT(ksal->getDate().
addSecs((ksal->getDawnAstronomicalTwilight() * 24.0 + Options::dawnOffset()) *
479 dusk = getGeo()->UTtoLT(ksal->getDate().
addSecs((ksal->getDuskAstronomicalTwilight() * 24.0 + Options::duskOffset()) *
491void SchedulerModuleState::calculateDawnDusk()
493 calculateDawnDusk(QDateTime(), m_Dawn, m_Dusk);
495 m_PreDawnDateTime = m_Dawn.addSecs(-60.0 * abs(Options::preDawnTime()));
496 emit updateNightTime();
499const GeoLocation *SchedulerModuleState::getGeo()
503 return KStarsData::Instance()->
geo();
506bool SchedulerModuleState::hasGeo()
508 return storedGeo !=
nullptr;
513 setupNextIteration(nextState, m_UpdatePeriodMs);
516void SchedulerModuleState::setupNextIteration(
SchedulerTimerState nextState,
int milliseconds)
518 if (iterationSetup())
520 qCDebug(KSTARS_EKOS_SCHEDULER)
521 << QString(
"Multiple setupNextIteration calls: current %1 %2, previous %3 %4")
522 .arg(nextState).arg(milliseconds).arg(timerState()).arg(timerInterval());
524 setTimerState(nextState);
526 if (iterationTimer().isActive())
529 int remaining = iterationTimer().remainingTime();
530 iterationTimer().stop();
531 setTimerInterval(std::max(0, milliseconds - remaining));
532 iterationTimer().start(timerInterval());
537 setTimerInterval(milliseconds);
539 setIterationSetup(
true);
542uint SchedulerModuleState::maxFailureAttempts()
544 return MAX_FAILURE_ATTEMPTS;
547void SchedulerModuleState::clearLog()
550 emit newLog(QString());
553bool SchedulerModuleState::checkRepeatSequence()
555 return (!Options::rememberJobProgress() && Options::schedulerRepeatEverything() &&
556 (Options::schedulerExecutionSequencesLimit() == 0
557 || 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