diff --git a/kstars/ekos/scheduler/scheduler.cpp b/kstars/ekos/scheduler/scheduler.cpp --- a/kstars/ekos/scheduler/scheduler.cpp +++ b/kstars/ekos/scheduler/scheduler.cpp @@ -1430,8 +1430,9 @@ startupB->setEnabled(false); shutdownB->setEnabled(false); + /* No, don't reset everything */ /* Reset and re-evaluate all scheduler jobs, then start the Scheduler */ - startJobEvaluation(); + /* startJobEvaluation(); */ state = SCHEDULER_RUNNING; emit newStatus(state); schedulerTimer.start(); @@ -1566,7 +1567,7 @@ /* Job is complete if its fixed completion time is passed */ if (job->getCompletionTime().isValid() && job->getCompletionTime() < now) { - job->setState(SchedulerJob::JOB_COMPLETE); + job->setState(SchedulerJob::JOB_IDLE); continue; } break; @@ -3109,6 +3110,9 @@ bool Scheduler::checkStatus() { + foreach (auto job, jobs) + job->updateJobCells(); + if (state == SCHEDULER_PAUSED) { if (currentJob == nullptr) @@ -3285,11 +3289,11 @@ if (isMountParked() == false) { appendLogText(i18n("Job '%1' current altitude (%2 degrees) crossed minimum constraint altitude (%3 degrees), " - "marking aborted.", currentJob->getName(), + "marking idle.", currentJob->getName(), QString("%L1").arg(p.alt().Degrees(), 0, 'f', minAltitude->decimals()), QString("%L1").arg(currentJob->getMinAltitude(), 0, 'f', minAltitude->decimals()))); - currentJob->setState(SchedulerJob::JOB_COMPLETE); + currentJob->setState(SchedulerJob::JOB_IDLE); stopCurrentJobAction(); findNextJob(); return; @@ -3311,10 +3315,10 @@ if (isMountParked() == false) { appendLogText(i18n("Job '%2' current moon separation (%1 degrees) is lower than minimum constraint (%3 " - "degrees), marking aborted.", + "degrees), marking idle.", moonSeparation, currentJob->getName(), currentJob->getMinMoonSeparation())); - currentJob->setState(SchedulerJob::JOB_COMPLETE); + currentJob->setState(SchedulerJob::JOB_IDLE); stopCurrentJobAction(); findNextJob(); return; @@ -3330,9 +3334,9 @@ { // Minute is a DOUBLE value, do not use i18np appendLogText(i18n( - "Job '%3' is now approaching astronomical twilight rise limit at %1 (%2 minutes safety margin), marking aborted.", + "Job '%3' is now approaching astronomical twilight rise limit at %1 (%2 minutes safety margin), marking idle.", preDawnDateTime.toString(), Options::preDawnTime(), currentJob->getName())); - currentJob->setState(SchedulerJob::JOB_COMPLETE); + currentJob->setState(SchedulerJob::JOB_IDLE); stopCurrentJobAction(); findNextJob(); return; @@ -4534,8 +4538,9 @@ Q_ASSERT_X(currentJob->getState() == SchedulerJob::JOB_ERROR || currentJob->getState() == SchedulerJob::JOB_ABORTED || - currentJob->getState() == SchedulerJob::JOB_COMPLETE, - __FUNCTION__, "Finding next job requires current to be in error, aborted or complete"); + currentJob->getState() == SchedulerJob::JOB_COMPLETE || + currentJob->getState() == SchedulerJob::JOB_IDLE, + __FUNCTION__, "Finding next job requires current to be in error, aborted, idle or complete"); jobTimer.stop(); @@ -4581,6 +4586,12 @@ setCurrentJob(nullptr); schedulerTimer.start(); } + else if (currentJob->getState() == SchedulerJob::JOB_IDLE) + { + // job constraints no longer valid, start re-evaluation + setCurrentJob(nullptr); + schedulerTimer.start(); + } // Job is complete, so check completion criteria to optimize processing // In any case, we're done whether the job completed successfully or not. else if (currentJob->getCompletionCondition() == SchedulerJob::FINISH_SEQUENCE) @@ -6700,7 +6711,7 @@ QTime const remainingTimeMs = QTime::fromMSecsSinceStartOfDay(std::lround((double) sleepTimer.remainingTime() * KStarsData::Instance()->clock()->scale() / newScale)); - appendLogText(i18n("Sleeping for %2 on simulation clock update until observation job %1 is ready...", currentJob->getName(), + appendLogText(i18n("Sleeping for %1 on simulation clock update until next observation job is ready...", remainingTimeMs.toString("hh:mm:ss"))); sleepTimer.stop(); sleepTimer.start(remainingTimeMs.msecsSinceStartOfDay()); @@ -7250,6 +7261,8 @@ bool Scheduler::shouldSchedulerSleep(SchedulerJob *currentJob) { + Q_ASSERT_X(nullptr != currentJob, __FUNCTION__, "There must be a valid current job for Scheduler to test sleep requirement"); + if (currentJob->getLightFramesRequired() == false) return false; @@ -7311,7 +7324,7 @@ sleepLabel->show(); // Warn the user if the next job is really far away - 60/5 = 12 times the lead time - if (nextObservationTime > Options::leadTime() * 60 * 12) + if (nextObservationTime > Options::leadTime() * 60 * 12 && !Options::preemptiveShutdown()) { dms delay(static_cast(nextObservationTime * 15.0 / 3600.0)); appendLogText(i18n( diff --git a/kstars/ekos/scheduler/schedulerjob.cpp b/kstars/ekos/scheduler/schedulerjob.cpp --- a/kstars/ekos/scheduler/schedulerjob.cpp +++ b/kstars/ekos/scheduler/schedulerjob.cpp @@ -169,8 +169,8 @@ if (JOB_ERROR == state) KNotification::event(QLatin1String("EkosSchedulerJobFail"), i18n("Ekos job failed (%1)", getName())); - /* If job becomes invalid, automatically reset its startup characteristics, and force its duration to be reestimated */ - if (JOB_INVALID == value) + /* If job becomes invalid or idle, automatically reset its startup characteristics, and force its duration to be reestimated */ + if (JOB_INVALID == value || JOB_IDLE == value) { setStartupCondition(fileStartupCondition); setStartupTime(fileStartupTime); @@ -237,7 +237,6 @@ altitudeCell = value; if (nullptr != altitudeCell) altitudeCell->setToolTip(i18n("Current altitude of the target of job '%1'.\n" - "The altitude at startup, if available, is displayed between parentheses.\n" "A rising target is indicated with an arrow going up.\n" "A setting target is indicated with an arrow going down.", name)); @@ -248,6 +247,7 @@ startupCell = value; if (nullptr != startupCell) startupCell->setToolTip(i18n("Startup time for job '%1', as estimated by the Scheduler.\n" + "The altitude at startup, if available, is displayed too.\n" "Fixed time from user or culmination time is marked with a chronometer symbol. ", name)); }