7#include "sequencejob.h"
9#include <knotification.h>
10#include <ekos_capture_debug.h>
11#include "capturedeviceadaptor.h"
12#include "skyobjects/skypoint.h"
13#include "ksnotification.h"
15#define MF_TIMER_TIMEOUT 90000
16#define MF_RA_DIFF_LIMIT 4
20QString
const &SequenceJob::ISOMarker(
"_ISO8601");
22const QStringList SequenceJob::StatusStrings()
24 static const QStringList names = {
i18n(
"Idle"),
i18n(
"In Progress"),
i18n(
"Error"),
i18n(
"Aborted"),
35SequenceJob::SequenceJob(XMLEle * root, QString targetName)
38 QSharedPointer<CameraState> sharedState;
39 sharedState.
reset(
new CameraState);
40 state.reset(
new SequenceJobState(sharedState));
42 devices.reset(
new CaptureDeviceAdaptor());
44 init(SequenceJob::JOBTYPE_BATCH, root, sharedState, targetName);
47SequenceJob::SequenceJob(
const QSharedPointer<CaptureDeviceAdaptor> cp,
48 const QSharedPointer<CameraState> sharedState,
49 SequenceJobType jobType, XMLEle *root, QString targetName)
52 init(jobType, root, sharedState, targetName);
55void Ekos::SequenceJob::init(SequenceJobType jobType, XMLEle *root,
56 QSharedPointer<Ekos::CameraState> sharedState,
57 const QString &targetName)
60 state.reset(
new SequenceJobState(sharedState));
62 loadFrom(root, targetName, jobType);
65 connect(state.data(), &SequenceJobState::prepareState,
this, &SequenceJob::prepareState);
66 connect(state.data(), &SequenceJobState::prepareComplete,
this, &SequenceJob::processPrepareComplete);
67 connect(state.data(), &SequenceJobState::abortCapture,
this, &SequenceJob::processAbortCapture);
68 connect(state.data(), &SequenceJobState::newLog,
this, &SequenceJob::newLog);
70 connect(state.data(), &SequenceJobState::initCaptureComplete,
this, &SequenceJob::capture);
77 auto placeholderPath = Ekos::PlaceholderPath();
78 placeholderPath.processJobInfo(
this);
81void SequenceJob::resetStatus(JOBStatus status)
84 setCalibrationStage(SequenceJobState::CAL_NONE);
98 m_JobProgressIgnored =
false;
106void SequenceJob::abort()
108 setStatus(JOB_ABORTED);
109 if (devices.data()->getActiveChip())
111 if (devices.data()->getActiveChip()->canAbort())
112 devices.data()->getActiveChip()->abortExposure();
113 devices.data()->getActiveChip()->setBatchMode(
false);
117void SequenceJob::done()
122int SequenceJob::getJobRemainingTime(
double estimatedDownloadTime)
124 double remaining = (getCoreProperty(SJ_Exposure).toDouble() +
125 estimatedDownloadTime +
126 getCoreProperty(SJ_Delay).toDouble() / 1000) *
127 (getCoreProperty(SJ_Count).toDouble() - getCompleted());
129 if (getStatus() == JOB_BUSY)
131 if (getExposeLeft() > 0.0)
132 remaining -= getCoreProperty(SJ_Exposure).toDouble() - getExposeLeft();
134 remaining += getExposeLeft() + estimatedDownloadTime;
137 return static_cast<int>(std::round(remaining));
140void SequenceJob::setStatus(JOBStatus
const in_status)
142 state->reset(in_status);
145void SequenceJob::setISO(
int index)
147 if (devices->getActiveChip())
149 setCoreProperty(SequenceJob::SJ_ISOIndex, index);
150 const auto isolist = devices->getActiveChip()->getISOList();
151 if (isolist.count() > index && index >= 0)
152 setCoreProperty(SequenceJob::SJ_ISO, isolist[index]);
156const QVariant SequenceJob::getRemoteDirectory()
const
158 if (getCoreProperty(SJ_RemoteDirectory).
toString().isEmpty())
159 return getCoreProperty(SJ_LocalDirectory);
161 return getCoreProperty(SJ_RemoteDirectory);
164QStringList SequenceJob::frameTypes()
const
166 if (!devices->getActiveCamera())
167 return QStringList({
"Light",
"Bias",
"Dark",
"Flat"});
169 ISD::CameraChip *tChip = devices->getActiveCamera()->getChip(ISD::CameraChip::PRIMARY_CCD);
171 return tChip->getFrameTypes();
174QStringList SequenceJob::filterLabels()
const
176 if (devices->getFilterManager().isNull())
177 return QStringList();
179 return devices->getFilterManager()->getFilterLabels();
183void SequenceJob::connectDeviceAdaptor()
185 devices->setCurrentSequenceJobState(state);
187 connect(state.data(), &SequenceJobState::readCurrentState, devices.data(),
188 &CaptureDeviceAdaptor::readCurrentState);
189 connect(state.data(), &SequenceJobState::flatSyncFocus, devices.data(),
190 &CaptureDeviceAdaptor::flatSyncFocus);
192 connect(devices.data(), &CaptureDeviceAdaptor::flatSyncFocusChanged, state.data(),
193 &SequenceJobState::flatSyncFocusChanged);
196void SequenceJob::disconnectDeviceAdaptor()
198 devices->disconnectDevices(state.data());
199 disconnect(state.data(), &SequenceJobState::readCurrentState, devices.data(),
200 &CaptureDeviceAdaptor::readCurrentState);
201 disconnect(state.data(), &SequenceJobState::flatSyncFocus, devices.data(),
202 &CaptureDeviceAdaptor::flatSyncFocus);
203 disconnect(devices.data(), &CaptureDeviceAdaptor::flatSyncFocusChanged, state.data(),
204 &SequenceJobState::flatSyncFocusChanged);
207void SequenceJob::startCapturing(
bool autofocusReady, FITSMode mode)
209 state->initCapture(getFrameType(), jobType() == SequenceJob::JOBTYPE_PREVIEW, autofocusReady, mode);
212QString SequenceJob::setCameraDeviceProperties()
215 QString logentry = QString(
"Capture exposure = %1 sec, type = %2").arg(getCoreProperty(SJ_Exposure).toDouble()).arg(
216 CCDFrameTypeNames[getFrameType()]);
217 logentry.
append(QString(
", filter = %1, upload mode = %2").arg(getCoreProperty(SJ_Filter).
toString()).arg(getUploadMode()));
220 QMapIterator<QString, QMap<QString, QVariant>> i(m_CustomProperties);
224 auto customProp = devices.data()->getActiveCamera()->getProperty(i.key());
227 QMap<QString, QVariant> elements = i.value();
228 QMapIterator<QString, QVariant> j(elements);
230 switch (customProp.getType())
234 auto sp = customProp.getSwitch();
238 auto oneSwitch = sp->findWidgetByName(j.key().toLatin1().data());
240 oneSwitch->setState(
static_cast<ISState
>(j.value().toInt()));
242 devices.data()->getActiveCamera()->sendNewProperty(sp);
247 auto tp = customProp.getText();
251 auto oneText = tp->findWidgetByName(j.key().toLatin1().data());
253 oneText->setText(j.value().toString().toLatin1().constData());
255 devices.data()->getActiveCamera()->sendNewProperty(tp);
260 auto np = customProp.getNumber();
264 auto oneNumber = np->findWidgetByName(j.key().toLatin1().data());
266 oneNumber->setValue(j.value().toDouble());
268 devices.data()->getActiveCamera()->sendNewProperty(np);
278 const int ISOIndex = getCoreProperty(SJ_ISOIndex).toInt();
281 logentry.
append(QString(
", ISO index = %1").arg(ISOIndex));
282 if (ISOIndex != devices.data()->getActiveChip()->getISOIndex())
283 devices.
data()->getActiveChip()->setISOIndex(ISOIndex);
286 const auto gain = getCoreProperty(SJ_Gain).toDouble();
289 logentry.
append(QString(
", gain = %1").arg(gain));
290 devices.
data()->getActiveCamera()->setGain(gain);
293 const auto offset = getCoreProperty(SJ_Offset).toDouble();
296 logentry.
append(QString(
", offset = %1").arg(offset));
297 devices.
data()->getActiveCamera()->setOffset(offset);
300 const auto remoteFormatDirectory = getCoreProperty(SJ_RemoteFormatDirectory).toString();
301 const auto remoteFormatFilename = getCoreProperty(SJ_RemoteFormatFilename).toString();
303 if (jobType() == SequenceJob::JOBTYPE_PREVIEW && !isVideo())
305 if (devices.data()->getActiveCamera()->getUploadMode() != ISD::Camera::UPLOAD_CLIENT)
306 devices.data()->getActiveCamera()->setUploadMode(ISD::Camera::UPLOAD_CLIENT);
309 devices.data()->getActiveCamera()->setUploadMode(m_UploadMode);
311 if (devices.data()->getActiveChip()->isBatchMode() &&
312 remoteFormatDirectory.isEmpty() ==
false &&
313 remoteFormatFilename.isEmpty() ==
false)
316 devices.data()->getActiveCamera()->setSERNameDirectory(remoteFormatFilename, remoteFormatDirectory);
318 devices.data()->getActiveCamera()->updateUploadSettings(remoteFormatDirectory, remoteFormatFilename);
325 devices.data()->getActiveCamera()->setUploadMode(m_UploadMode);
327 devices.data()->getActiveCamera()->setStreamRecording(getCoreProperty(SJ_Format).
toString());
328 devices.data()->getActiveCamera()->setStreamEncoding(getCoreProperty(SJ_Encoding).
toString());
332 devices.data()->getActiveChip()->setBatchMode(jobType() != SequenceJob::JOBTYPE_PREVIEW);
333 devices.data()->getActiveCamera()->setSeqPrefix(getCoreProperty(SJ_FullPrefix).
toString());
334 logentry.
append(QString(
", batch mode = %1, seq prefix = %2").arg(jobType() != SequenceJob::JOBTYPE_PREVIEW ?
"true" :
335 "false").arg(getCoreProperty(SJ_FullPrefix).
toString()));
338 devices.
data()->getActiveCamera()->setCaptureFormat(getCoreProperty(SJ_Format).
toString());
339 devices.data()->getActiveCamera()->setEncodingFormat(getCoreProperty(SJ_Encoding).
toString());
340 devices.data()->getActiveChip()->setFrameType(getFrameType());
342 if (getUploadMode() != ISD::Camera::UPLOAD_CLIENT)
343 logentry.
append(QString(
", remote dir = %1, remote format = %2").arg(remoteFormatDirectory).arg(remoteFormatFilename));
345 logentry.
append(QString(
", format = %1, encoding = %2").arg(getCoreProperty(SJ_Format).
toString()).arg(getCoreProperty(
349 int currentBinX = 1, currentBinY = 1;
350 devices.
data()->getActiveChip()->getBinning(¤tBinX, ¤tBinY);
352 const auto binning = getCoreProperty(SJ_Binning).toPoint();
356 if (devices.data()->getActiveChip()->canBin())
358 if (devices.data()->getActiveChip()->setBinning(binning.x(), binning.y()) ==
false)
360 qCWarning(KSTARS_EKOS_CAPTURE()) <<
"Cannot set binning to " <<
"x =" << binning.x() <<
", y =" << binning.y();
361 setStatus(JOB_ERROR);
362 emit captureStarted(CAPTURE_BIN_ERROR);
365 logentry.
append(QString(
", binning = %1x%2").arg(binning.x()).arg(binning.y()));
368 logentry.
append(QString(
", Cannot bin"));
371 const auto roi = getCoreProperty(SJ_ROI).toRect();
373 if (devices.data()->getActiveChip()->canSubframe())
375 if ((roi.width() > 0 && roi.height() > 0) && devices.data()->getActiveChip()->setFrame(roi.x(),
379 currentBinX != binning.x()) ==
false)
381 qCWarning(KSTARS_EKOS_CAPTURE()) <<
"Cannot set ROI to " <<
"x =" << roi.x() <<
", y =" << roi.y() <<
", widht =" <<
382 roi.width() <<
"height =" << roi.height();
383 setStatus(JOB_ERROR);
384 emit captureStarted(CAPTURE_FRAME_ERROR);
387 logentry.
append(QString(
", ROI = (%1+%2, %3+%4)").arg(roi.x()).arg(roi.width()).arg(roi.y()).arg(roi.width()));
390 logentry.
append(
", Cannot subframe");
395void SequenceJob::capture(FITSMode mode)
397 if (!devices.data()->getActiveCamera() || !devices.data()->getActiveChip())
400 QString logentry = setCameraDeviceProperties();
403 setStatus(getStatus());
407 devices.data()->getActiveCamera()->setStreamExposure(getCoreProperty(SJ_Exposure).toDouble());
408 auto frames = getCoreProperty(SJ_Count).toUInt();
409 auto success = devices.data()->getActiveCamera()->startFramesRecording(frames);
412 qCWarning(KSTARS_EKOS_CAPTURE) <<
"Start recording failed!";
413 emit captureStarted(CAPTURE_FRAME_ERROR);
425 devices.data()->getActiveChip()->setCaptureMode(mode);
426 devices.data()->getActiveChip()->setCaptureFilter(FITS_NONE);
428 m_ExposeLeft = getCoreProperty(SJ_Exposure).toDouble();
429 devices.data()->getActiveChip()->capture(m_ExposeLeft);
432 emit captureStarted(CAPTURE_OK);
435 qCInfo(KSTARS_EKOS_CAPTURE) << logentry;
438void SequenceJob::setTargetFilter(
int pos,
const QString &name)
440 state->targetFilterID = pos;
441 setCoreProperty(SJ_Filter, name);
444double SequenceJob::getExposeLeft()
const
449void SequenceJob::setExposeLeft(
double value)
451 m_ExposeLeft = value;
455int SequenceJob::getCaptureRetires()
const
457 return m_CaptureRetires;
460void SequenceJob::setCaptureRetires(
int value)
462 m_CaptureRetires = value;
465int SequenceJob::getCurrentFilter()
const
467 return state->m_CameraState->currentFilterID;
470ISD::Mount::PierSide SequenceJob::getPierSide()
const
472 return state->m_CameraState->getPierSide();
476void SequenceJob::setUploadMode(ISD::Camera::UploadMode value)
478 m_UploadMode = value;
481ISD::Camera::UploadMode SequenceJob::getUploadMode()
const
487void SequenceJob::setCalibrationPreAction(uint32_t value)
489 state->m_CalibrationPreAction = value;
492uint32_t SequenceJob::getCalibrationPreAction()
const
494 return state->m_CalibrationPreAction;
497void SequenceJob::setWallCoord(
const SkyPoint &value)
499 state->wallCoord = value;
502const SkyPoint &SequenceJob::getWallCoord()
const
504 return state->wallCoord;
508void SequenceJob::setFlatFieldDuration(FlatFieldDuration value)
510 m_FlatFieldDuration = value;
514FlatFieldDuration SequenceJob::getFlatFieldDuration()
const
516 return m_FlatFieldDuration;
519void SequenceJob::setJobProgressIgnored(
bool value)
521 m_JobProgressIgnored = value;
524bool SequenceJob::getJobProgressIgnored()
const
526 return m_JobProgressIgnored;
529void SequenceJob::updateDeviceStates()
531 setLightBox(devices->lightBox());
532 addMount(devices->mount());
533 setDome(devices->dome());
534 setDustCap(devices->dustCap());
537void SequenceJob::setLightBox(ISD::LightBox * lightBox)
539 state->m_CameraState->hasLightBox = (lightBox !=
nullptr);
542void SequenceJob::setDustCap(ISD::DustCap * dustCap)
544 state->m_CameraState->hasDustCap = (dustCap !=
nullptr);
547void SequenceJob::addMount(ISD::Mount * scope)
549 state->m_CameraState->hasTelescope = (scope !=
nullptr);
552void SequenceJob::setDome(ISD::Dome * dome)
554 state->m_CameraState->hasDome = (dome !=
nullptr);
557double SequenceJob::currentTemperature()
const
559 return devices->cameraTemperature();
562double SequenceJob::currentGain()
const
564 return devices->cameraGain();
567double SequenceJob::currentOffset()
const
569 return devices->cameraOffset();
572void SequenceJob::prepareCapture()
575 switch (getFrameType())
579 state->prepareLightFrameCapture(getCoreProperty(SJ_EnforceTemperature).toBool(),
580 jobType() == SequenceJob::JOBTYPE_PREVIEW);
583 state->prepareFlatFrameCapture(getCoreProperty(SJ_EnforceTemperature).toBool(),
584 jobType() == SequenceJob::JOBTYPE_PREVIEW);
587 state->prepareDarkFrameCapture(getCoreProperty(SJ_EnforceTemperature).toBool(),
588 jobType() == SequenceJob::JOBTYPE_PREVIEW);
591 state->prepareBiasFrameCapture(getCoreProperty(SJ_EnforceTemperature).toBool(),
592 jobType() == SequenceJob::JOBTYPE_PREVIEW);
596 processPrepareComplete();
601void SequenceJob::processPrepareComplete(
bool success)
603 emit prepareComplete(success);
606void SequenceJob::processAbortCapture()
608 disconnectDeviceAdaptor();
612IPState SequenceJob::checkFlatFramePendingTasksCompleted()
618void SequenceJob::setCoreProperty(PropertyID
id,
const QVariant &value)
623 case SJ_RemoteDirectory:
626 if (remoteDir.endsWith(
'/'))
629 m_CoreProperties[id] = remoteDir;
638 m_CoreProperties[id] = value;
641QVariant SequenceJob::getCoreProperty(PropertyID
id)
const
643 return m_CoreProperties[id];
646void SequenceJob::loadFrom(XMLEle *root,
const QString &targetName, SequenceJobType jobType)
651 m_CoreProperties[SJ_Exposure] = -1;
652 m_CoreProperties[SJ_Gain] = -1;
653 m_CoreProperties[SJ_Offset] = -1;
654 m_CoreProperties[SJ_ISOIndex] = -1;
655 m_CoreProperties[SJ_Count] = -1;
656 m_CoreProperties[SJ_Delay] = -1;
657 m_CoreProperties[SJ_Binning] = QPoint(1, 1);
658 m_CoreProperties[SJ_ROI] = QRect(0, 0, 0, 0);
659 m_CoreProperties[SJ_EnforceTemperature] =
false;
660 m_CoreProperties[SJ_GuiderActive] =
false;
661 m_CoreProperties[SJ_DitherPerJobEnabled] =
true;
662 m_CoreProperties[SJ_DitherPerJobFrequency] = 0;
663 m_CoreProperties[SJ_Encoding] =
"FITS";
666 if (targetName !=
"")
667 setCoreProperty(SequenceJob::SJ_TargetName, targetName);
672 bool isDarkFlat =
false;
677 for (ep = nextXMLEle(root, 1); ep !=
nullptr; ep = nextXMLEle(root, 0))
679 if (!strcmp(tagXMLEle(ep),
"Exposure"))
680 setCoreProperty(SequenceJob::SJ_Exposure, cLocale.
toDouble(pcdataXMLEle(ep)));
681 else if (!strcmp(tagXMLEle(ep),
"Format"))
682 setCoreProperty(SequenceJob::SJ_Format, QString(pcdataXMLEle(ep)));
683 else if (!strcmp(tagXMLEle(ep),
"Encoding"))
685 setCoreProperty(SequenceJob::SJ_Encoding, QString(pcdataXMLEle(ep)));
687 else if (!strcmp(tagXMLEle(ep),
"Binning"))
689 QPoint binning(1, 1);
690 subEP = findXMLEle(ep,
"X");
692 binning.setX(cLocale.
toInt(pcdataXMLEle(subEP)));
693 subEP = findXMLEle(ep,
"Y");
695 binning.setY(cLocale.
toInt(pcdataXMLEle(subEP)));
697 setCoreProperty(SequenceJob::SJ_Binning, binning);
699 else if (!strcmp(tagXMLEle(ep),
"Frame"))
701 QRect roi(0, 0, 0, 0);
702 subEP = findXMLEle(ep,
"X");
704 roi.setX(cLocale.
toInt(pcdataXMLEle(subEP)));
705 subEP = findXMLEle(ep,
"Y");
707 roi.setY(cLocale.
toInt(pcdataXMLEle(subEP)));
708 subEP = findXMLEle(ep,
"W");
710 roi.setWidth(cLocale.
toInt(pcdataXMLEle(subEP)));
711 subEP = findXMLEle(ep,
"H");
713 roi.setHeight(cLocale.
toInt(pcdataXMLEle(subEP)));
715 setCoreProperty(SequenceJob::SJ_ROI, roi);
717 else if (!strcmp(tagXMLEle(ep),
"Temperature"))
719 setTargetTemperature(cLocale.
toDouble(pcdataXMLEle(ep)));
722 if (!strcmp(findXMLAttValu(ep,
"force"),
"true"))
723 setCoreProperty(SequenceJob::SJ_EnforceTemperature,
true);
724 else if (!strcmp(findXMLAttValu(ep,
"force"),
"false"))
725 setCoreProperty(SequenceJob::SJ_EnforceTemperature,
false);
727 else if (!strcmp(tagXMLEle(ep),
"Filter"))
729 const auto name = pcdataXMLEle(ep);
730 const auto index = std::max(1, (
int)(filterLabels().indexOf(name) + 1));
731 setTargetFilter(index, name);
733 else if (!strcmp(tagXMLEle(ep),
"Type"))
735 int index = frameTypes().indexOf(pcdataXMLEle(ep));
736 setFrameType(
static_cast<CCDFrameType
>(qMax(0, index)));
738 else if (!strcmp(tagXMLEle(ep),
"TargetName"))
740 QString jobTarget = pcdataXMLEle(ep);
744 setCoreProperty(SequenceJob::SJ_TargetName, QString(jobTarget));
747 qWarning(KSTARS_EKOS_CAPTURE) << QString(
"Sequence job target name %1 ignored in favor of %2.").arg(jobTarget, targetName);
749 else if (!strcmp(tagXMLEle(ep),
"Prefix"))
751 qWarning(KSTARS_EKOS_CAPTURE) << QString(
"Sequence job is using outdated format. Please create a new sequence file");
753 subEP = findXMLEle(ep,
"RawPrefix");
756 QString jobTarget = pcdataXMLEle(subEP);
760 setCoreProperty(SequenceJob::SJ_TargetName, QString(jobTarget));
763 qWarning(KSTARS_EKOS_CAPTURE) << QString(
"Sequence job target name %1 ignored in favor of %2.").arg(jobTarget, targetName);
765 bool filterEnabled =
false, expEnabled =
false, tsEnabled =
false;
766 subEP = findXMLEle(ep,
"FilterEnabled");
768 filterEnabled = !strcmp(
"1", pcdataXMLEle(subEP));
769 subEP = findXMLEle(ep,
"ExpEnabled");
771 expEnabled = !strcmp(
"1", pcdataXMLEle(subEP));
772 subEP = findXMLEle(ep,
"TimeStampEnabled");
774 tsEnabled = !strcmp(
"1", pcdataXMLEle(subEP));
776 setCoreProperty(SequenceJob::SJ_PlaceholderFormat,
777 PlaceholderPath::defaultFormat(filterEnabled, expEnabled, tsEnabled));
779 else if (!strcmp(tagXMLEle(ep),
"Count"))
781 setCoreProperty(SequenceJob::SJ_Count, cLocale.
toInt(pcdataXMLEle(ep)));
783 else if (!strcmp(tagXMLEle(ep),
"Delay"))
785 setCoreProperty(SequenceJob::SJ_Delay, cLocale.
toInt(pcdataXMLEle(ep)) * 1000);
787 else if (!strcmp(tagXMLEle(ep),
"PostCaptureScript"))
791 else if (!strcmp(tagXMLEle(ep),
"PreCaptureScript"))
795 else if (!strcmp(tagXMLEle(ep),
"PostJobScript"))
799 else if (!strcmp(tagXMLEle(ep),
"PreJobScript"))
803 else if (!strcmp(tagXMLEle(ep),
"GuideDitherPerJob"))
805 const int value = cLocale.
toInt(pcdataXMLEle(ep));
808 setCoreProperty(SequenceJob::SJ_DitherPerJobFrequency, value);
809 setCoreProperty(SequenceJob::SJ_DitherPerJobEnabled,
true);
812 setCoreProperty(SequenceJob::SJ_DitherPerJobEnabled,
false);
814 else if (!strcmp(tagXMLEle(ep),
"FITSDirectory"))
816 setCoreProperty(SequenceJob::SJ_LocalDirectory, QString(pcdataXMLEle(ep)));
818 else if (!strcmp(tagXMLEle(ep),
"PlaceholderFormat"))
820 setCoreProperty(SequenceJob::SJ_PlaceholderFormat, QString(pcdataXMLEle(ep)));
822 else if (!strcmp(tagXMLEle(ep),
"PlaceholderSuffix"))
824 setCoreProperty(SequenceJob::SJ_PlaceholderSuffix, cLocale.
toUInt(pcdataXMLEle(ep)));
826 else if (!strcmp(tagXMLEle(ep),
"RemoteDirectory"))
828 setCoreProperty(SequenceJob::SJ_RemoteDirectory, QString(pcdataXMLEle(ep)));
830 else if (!strcmp(tagXMLEle(ep),
"UploadMode"))
832 setUploadMode(
static_cast<ISD::Camera::UploadMode
>(cLocale.
toInt(pcdataXMLEle(ep))));
834 else if (!strcmp(tagXMLEle(ep),
"ISOIndex"))
836 setISO(cLocale.
toInt(pcdataXMLEle(ep)));
838 else if (!strcmp(tagXMLEle(ep),
"Rotation"))
840 setTargetRotation(cLocale.
toDouble(pcdataXMLEle(ep)));
842 else if (!strcmp(tagXMLEle(ep),
"Properties"))
844 QMap<QString, QMap<QString, QVariant>> propertyMap;
846 for (subEP = nextXMLEle(ep, 1); subEP !=
nullptr; subEP = nextXMLEle(ep, 0))
848 QMap<QString, QVariant> elements;
849 XMLEle * oneElement =
nullptr;
850 for (oneElement = nextXMLEle(subEP, 1); oneElement !=
nullptr; oneElement = nextXMLEle(subEP, 0))
852 const char *
name = findXMLAttValu(oneElement,
"name");
855 auto xmlValue = pcdataXMLEle(oneElement);
857 auto value = cLocale.
toDouble(xmlValue, &ok);
859 elements[
name] = value;
861 elements[
name] = *xmlValue;
864 const char *
name = findXMLAttValu(subEP,
"name");
865 propertyMap[
name] = elements;
868 setCustomProperties(propertyMap);
870 setCoreProperty(SequenceJob::SJ_Gain, devices->cameraGain(propertyMap));
871 setCoreProperty(SequenceJob::SJ_Offset, devices->cameraOffset(propertyMap));
873 else if (!strcmp(tagXMLEle(ep),
"Calibration"))
876 subEP = findXMLEle(ep,
"PreAction");
879 XMLEle * typeEP = findXMLEle(subEP,
"Type");
882 setCalibrationPreAction(cLocale.
toUInt(pcdataXMLEle(typeEP)));
883 if (getCalibrationPreAction() & CAPTURE_PREACTION_WALL)
885 XMLEle * azEP = findXMLEle(subEP,
"Az");
886 XMLEle * altEP = findXMLEle(subEP,
"Alt");
890 setCalibrationPreAction((getCalibrationPreAction() & ~CAPTURE_PREACTION_PARK_MOUNT) | CAPTURE_PREACTION_WALL);
894 setWallCoord(wallCoord);
898 qCWarning(KSTARS_EKOS_CAPTURE) <<
"Wall position coordinates missing, disabling slew to wall position action.";
899 setCalibrationPreAction((getCalibrationPreAction() & ~CAPTURE_PREACTION_WALL) | CAPTURE_PREACTION_NONE);
906 subEP = findXMLEle(ep,
"FlatSource");
909 XMLEle * typeEP = findXMLEle(subEP,
"Type");
913 setCalibrationPreAction(CAPTURE_PREACTION_NONE);
914 if (!strcmp(pcdataXMLEle(typeEP),
"Wall"))
916 XMLEle * azEP = findXMLEle(subEP,
"Az");
917 XMLEle * altEP = findXMLEle(subEP,
"Alt");
921 setCalibrationPreAction((getCalibrationPreAction() & ~CAPTURE_PREACTION_PARK_MOUNT) | CAPTURE_PREACTION_WALL);
925 setWallCoord(wallCoord);
932 subEP = findXMLEle(ep,
"PreMountPark");
933 if (subEP && !strcmp(pcdataXMLEle(subEP),
"True"))
934 setCalibrationPreAction(getCalibrationPreAction() | CAPTURE_PREACTION_PARK_MOUNT);
937 subEP = findXMLEle(ep,
"PreDomePark");
938 if (subEP && !strcmp(pcdataXMLEle(subEP),
"True"))
939 setCalibrationPreAction(getCalibrationPreAction() | CAPTURE_PREACTION_PARK_DOME);
941 subEP = findXMLEle(ep,
"FlatDuration");
944 const char * dark = findXMLAttValu(subEP,
"dark");
945 isDarkFlat = !strcmp(dark,
"true");
947 XMLEle * typeEP = findXMLEle(subEP,
"Type");
950 if (!strcmp(pcdataXMLEle(typeEP),
"Manual"))
951 setFlatFieldDuration(DURATION_MANUAL);
954 XMLEle * aduEP = findXMLEle(subEP,
"Value");
957 setFlatFieldDuration(DURATION_ADU);
958 setCoreProperty(SequenceJob::SJ_TargetADU, QVariant(cLocale.
toDouble(pcdataXMLEle(aduEP))));
961 aduEP = findXMLEle(subEP,
"Tolerance");
964 setCoreProperty(SequenceJob::SJ_TargetADUTolerance, QVariant(cLocale.
toDouble(pcdataXMLEle(aduEP))));
966 aduEP = findXMLEle(subEP,
"SkyFlat");
969 setCoreProperty(SequenceJob::SJ_SkyFlat, (
bool)!strcmp(pcdataXMLEle(aduEP),
"true"));
975 setJobType(SequenceJob::JOBTYPE_DARKFLAT);
978void SequenceJob::saveTo(QTextStream &outstream,
const QLocale &cLocale)
const
980 auto roi = getCoreProperty(SequenceJob::SJ_ROI).toRect();
981 auto ditherPerJobEnabled = getCoreProperty(SequenceJob::SJ_DitherPerJobEnabled).toBool();
982 auto ditherPerJobFrequency = getCoreProperty(SequenceJob::SJ_DitherPerJobFrequency).toInt();
986 outstream <<
"<Exposure>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_Exposure).toDouble()) <<
"</Exposure>" <<
988 outstream <<
"<Format>" << getCoreProperty(SequenceJob::SJ_Format).toString() <<
"</Format>" <<
Qt::endl;
989 outstream <<
"<Encoding>" << getCoreProperty(SequenceJob::SJ_Encoding).toString() <<
"</Encoding>" <<
Qt::endl;
990 outstream <<
"<Binning>" <<
Qt::endl;
991 outstream <<
"<X>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_Binning).toPoint().x()) <<
"</X>" <<
Qt::endl;
992 outstream <<
"<Y>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_Binning).toPoint().y()) <<
"</Y>" <<
Qt::endl;
993 outstream <<
"</Binning>" <<
Qt::endl;
999 outstream <<
"</Frame>" <<
Qt::endl;
1000 if (getTargetTemperature() != Ekos::INVALID_VALUE)
1001 outstream <<
"<Temperature force='" << (getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool() ?
"true" :
1003 << cLocale.
toString(getTargetTemperature()) <<
"</Temperature>" <<
Qt::endl;
1004 if (getTargetFilter() >= 0)
1005 outstream <<
"<Filter>" << getCoreProperty(SequenceJob::SJ_Filter).toString() <<
"</Filter>" <<
Qt::endl;
1006 outstream <<
"<Type>" << frameTypes()[getFrameType()] <<
"</Type>" <<
Qt::endl;
1007 outstream <<
"<Count>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_Count).toInt()) <<
"</Count>" <<
Qt::endl;
1009 outstream <<
"<Delay>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_Delay).toInt() / 1000.0) <<
"</Delay>" <<
1011 if (getCoreProperty(SequenceJob::SJ_TargetName) !=
"")
1012 outstream <<
"<TargetName>" << getCoreProperty(SequenceJob::SJ_TargetName).toString() <<
"</TargetName>" <<
Qt::endl;
1021 outstream <<
"<GuideDitherPerJob>"
1022 << cLocale.
toString(ditherPerJobEnabled ? ditherPerJobFrequency : -1) <<
"</GuideDitherPerJob>" <<
1024 outstream <<
"<FITSDirectory>" << getCoreProperty(SequenceJob::SJ_LocalDirectory).toString() <<
"</FITSDirectory>" <<
1026 outstream <<
"<PlaceholderFormat>" << getCoreProperty(SequenceJob::SJ_PlaceholderFormat).toString() <<
1027 "</PlaceholderFormat>" <<
1029 outstream <<
"<PlaceholderSuffix>" << getCoreProperty(SequenceJob::SJ_PlaceholderSuffix).toUInt() <<
1030 "</PlaceholderSuffix>" <<
1032 outstream <<
"<UploadMode>" << getUploadMode() <<
"</UploadMode>" <<
Qt::endl;
1033 if (getCoreProperty(SequenceJob::SJ_RemoteDirectory).
toString().isEmpty() ==
false)
1034 outstream <<
"<RemoteDirectory>" << getCoreProperty(SequenceJob::SJ_RemoteDirectory).toString() <<
"</RemoteDirectory>"
1036 if (getCoreProperty(SequenceJob::SJ_ISOIndex).toInt() != -1)
1037 outstream <<
"<ISOIndex>" << (getCoreProperty(SequenceJob::SJ_ISOIndex).toInt()) <<
"</ISOIndex>" <<
Qt::endl;
1038 if (getTargetRotation() != Ekos::INVALID_VALUE)
1039 outstream <<
"<Rotation>" << (getTargetRotation()) <<
"</Rotation>" <<
Qt::endl;
1040 QMapIterator<QString, QMap<QString, QVariant>> customIter(getCustomProperties());
1041 outstream <<
"<Properties>" <<
Qt::endl;
1042 while (customIter.hasNext())
1045 outstream <<
"<PropertyVector name='" << customIter.key() <<
"'>" <<
Qt::endl;
1046 QMap<QString, QVariant> elements = customIter.
value();
1047 QMapIterator<QString, QVariant> iter(elements);
1048 while (iter.hasNext())
1053 outstream <<
"<OneElement name='" << iter.key()
1054 <<
"'>" << iter.value().toString() <<
"</OneElement>" <<
Qt::endl;
1058 outstream <<
"<OneElement name='" << iter.key()
1059 <<
"'>" << iter.value().toDouble() <<
"</OneElement>" <<
Qt::endl;
1062 outstream <<
"</PropertyVector>" <<
Qt::endl;
1064 outstream <<
"</Properties>" <<
Qt::endl;
1066 outstream <<
"<Calibration>" <<
Qt::endl;
1067 outstream <<
"<PreAction>" <<
Qt::endl;
1068 outstream << QString(
"<Type>%1</Type>").arg(getCalibrationPreAction()) <<
Qt::endl;
1069 if (getCalibrationPreAction() & CAPTURE_PREACTION_WALL)
1071 outstream <<
"<Az>" << cLocale.
toString(getWallCoord().az().Degrees()) <<
"</Az>" <<
Qt::endl;
1072 outstream <<
"<Alt>" << cLocale.
toString(getWallCoord().alt().Degrees()) <<
"</Alt>" <<
Qt::endl;
1074 outstream <<
"</PreAction>" <<
Qt::endl;
1076 outstream <<
"<FlatDuration dark='" << (jobType() == SequenceJob::JOBTYPE_DARKFLAT ?
"true" :
"false")
1078 if (getFlatFieldDuration() == DURATION_MANUAL)
1079 outstream <<
"<Type>Manual</Type>" <<
Qt::endl;
1082 outstream <<
"<Type>ADU</Type>" <<
Qt::endl;
1083 outstream <<
"<Value>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_TargetADU).toDouble()) <<
"</Value>" <<
1085 outstream <<
"<Tolerance>" << cLocale.
toString(getCoreProperty(SequenceJob::SJ_TargetADUTolerance).toDouble()) <<
1087 outstream <<
"<SkyFlat>" << (getCoreProperty(SequenceJob::SJ_SkyFlat).toBool() ?
"true" :
"false") <<
1090 outstream <<
"</FlatDuration>" <<
Qt::endl;
1091 outstream <<
"</Calibration>" <<
Qt::endl;
void setAlt(dms alt)
Sets Alt, the Altitude.
void setAz(dms az)
Sets Az, the Azimuth.
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
@ SCRIPT_POST_CAPTURE
Script to run after a sequence capture is completed.
@ SCRIPT_POST_JOB
Script to run after a sequence job is completed.
@ SCRIPT_PRE_CAPTURE
Script to run before a sequence capture is started.
@ SCRIPT_PRE_JOB
Script to run before a sequence job is started.
QString name(StandardAction id)
double toDouble(QStringView s, bool *ok) const const
int toInt(QStringView s, bool *ok) const const
QString toString(QDate date, FormatType format) const const
uint toUInt(QStringView s, bool *ok) const const
T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QString & append(QChar ch)
bool isEmpty() const const
QTextStream & endl(QTextStream &stream)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const