File indexing completed on 2024-04-28 07:33:05
0001 /* 0002 Helper class of KStars UI capture tests 0003 0004 SPDX-FileCopyrightText: 2020 Wolfgang Reissenberger <sterne-jaeger@openfuture.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "test_ekos_capture_helper.h" 0010 0011 #include "test_ekos.h" 0012 #include "ekos/capture/scriptsmanager.h" 0013 #include "ekos/capture/capture.h" 0014 #include "ekos/scheduler/scheduler.h" 0015 #include "Options.h" 0016 0017 TestEkosCaptureHelper::TestEkosCaptureHelper(QString guider) : TestEkosHelper(guider) {} 0018 0019 void TestEkosCaptureHelper::init() 0020 { 0021 TestEkosHelper::init(); 0022 QStandardPaths::setTestModeEnabled(true); 0023 QFileInfo test_dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation), "test"); 0024 destination = new QTemporaryDir(test_dir.absolutePath()); 0025 QVERIFY(destination->isValid()); 0026 QVERIFY(destination->autoRemove()); 0027 } 0028 0029 void TestEkosCaptureHelper::cleanup() 0030 { 0031 // remove destination directory 0032 if (destination != nullptr) 0033 destination->remove(); 0034 delete destination; 0035 } 0036 0037 0038 bool TestEkosCaptureHelper::startCapturing(bool checkCapturing) 0039 { 0040 // switch to the capture module 0041 KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(Ekos::Manager::Instance()->captureModule(), 1000)); 0042 0043 // check if capture is in a stopped state 0044 KWRAP_SUB(QVERIFY(getCaptureStatus() == Ekos::CAPTURE_IDLE || getCaptureStatus() == Ekos::CAPTURE_ABORTED 0045 || getCaptureStatus() == Ekos::CAPTURE_COMPLETE)); 0046 0047 // ensure at least one capture is started if requested 0048 if (checkCapturing) 0049 expectedCaptureStates.enqueue(Ekos::CAPTURE_CAPTURING); 0050 // press start 0051 KTRY_GADGET_SUB(Ekos::Manager::Instance()->captureModule(), QPushButton, startB); 0052 KTRY_CLICK_SUB(Ekos::Manager::Instance()->captureModule(), startB); 0053 0054 // check if capturing has started 0055 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT_SUB(expectedCaptureStates, 120000); 0056 // all checks succeeded 0057 return true; 0058 } 0059 0060 bool TestEkosCaptureHelper::stopCapturing() 0061 { 0062 // check if capture is in a stopped state 0063 if (getCaptureStatus() == Ekos::CAPTURE_IDLE || getCaptureStatus() == Ekos::CAPTURE_ABORTED 0064 || getCaptureStatus() == Ekos::CAPTURE_COMPLETE) 0065 return true; 0066 0067 // switch to the capture module 0068 KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(Ekos::Manager::Instance()->captureModule(), 1000)); 0069 0070 // else press stop 0071 expectedCaptureStates.enqueue(Ekos::CAPTURE_ABORTED); 0072 KTRY_GADGET_SUB(Ekos::Manager::Instance()->captureModule(), QPushButton, startB); 0073 KTRY_CLICK_SUB(Ekos::Manager::Instance()->captureModule(), startB); 0074 0075 // check if capturing has stopped 0076 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT_SUB(expectedCaptureStates, 5000); 0077 // all checks succeeded 0078 return true; 0079 } 0080 0081 QString TestEkosCaptureHelper::calculateSignature(QString target, QString filter, QString fitsDirectory) 0082 { 0083 if (target == "") 0084 return fitsDirectory + QDir::separator() + "Light" + QDir::separator() + filter + QDir::separator() + "Light_" + filter + 0085 "_"; 0086 else 0087 return fitsDirectory + QDir::separator() + target + QDir::separator() + "Light" + QDir::separator() + filter + 0088 QDir::separator() + target + "_" + "Light_" + filter + "_"; 0089 } 0090 0091 QStringList TestEkosCaptureHelper::searchFITS(const QDir &dir) const 0092 { 0093 QStringList list = dir.entryList(QDir::Files); 0094 0095 //foreach (auto &f, list) 0096 // QWARN(QString(dir.path()+'/'+f).toStdString().c_str()); 0097 0098 foreach (auto &d, dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) 0099 list.append(searchFITS(QDir(dir.path() + '/' + d))); 0100 0101 return list; 0102 } 0103 0104 void TestEkosCaptureHelper::ensureCCDShutter(bool shutter) 0105 { 0106 if (m_CCDDevice != "") 0107 { 0108 // ensure that we know that the CCD has a shutter 0109 QStringList shutterlessCCDs = Options::shutterlessCCDs(); 0110 QStringList shutterfulCCDs = Options::shutterfulCCDs(); 0111 if (shutter) 0112 { 0113 // remove CCD device from shutterless CCDs 0114 shutterlessCCDs.removeAll(m_CCDDevice); 0115 Options::setShutterlessCCDs(shutterlessCCDs); 0116 // add CCD device if necessary to shutterful CCDs 0117 if (! shutterfulCCDs.contains(m_CCDDevice)) 0118 { 0119 shutterfulCCDs.append(m_CCDDevice); 0120 Options::setShutterfulCCDs(shutterfulCCDs); 0121 } 0122 } 0123 else 0124 { 0125 // remove CCD device from shutterful CCDs 0126 shutterfulCCDs.removeAll(m_CCDDevice); 0127 Options::setShutterfulCCDs(shutterfulCCDs); 0128 // add CCD device if necessary to shutterless CCDs 0129 if (! shutterlessCCDs.contains(m_CCDDevice)) 0130 { 0131 shutterlessCCDs.append(m_CCDDevice); 0132 Options::setShutterlessCCDs(shutterlessCCDs); 0133 } 0134 } 0135 0136 } 0137 } 0138 0139 0140 QDir *TestEkosCaptureHelper::getImageLocation() 0141 { 0142 if (imageLocation == nullptr || imageLocation->exists() == false) 0143 imageLocation = new QDir(destination->path() + "/images"); 0144 0145 return imageLocation; 0146 } 0147 0148 bool TestEkosCaptureHelper::fillCaptureSequences(QString target, QString sequence, double exptime, QString fitsDirectory, 0149 int delay, QString format) 0150 { 0151 if (sequence == "") 0152 return true; 0153 0154 for (QString value : sequence.split(",")) 0155 { 0156 KVERIFY_SUB(value.indexOf(":") > -1); 0157 QString filter = value.left(value.indexOf(":")); 0158 int count = value.right(value.length() - value.indexOf(":") - 1).toInt(); 0159 KTRY_SET_LINEEDIT_SUB(Ekos::Manager::Instance()->captureModule(), placeholderFormatT, format); 0160 if (count > 0) 0161 KWRAP_SUB(KTRY_CAPTURE_ADD_LIGHT(exptime, count, delay, filter, target, fitsDirectory)); 0162 // ensure that no old values are present 0163 Ekos::Manager::Instance()->captureModule()->setCapturedFramesMap(calculateSignature(target, filter, fitsDirectory), 0); 0164 } 0165 0166 return true; 0167 } 0168 0169 bool TestEkosCaptureHelper::fillScriptManagerDialog(const QMap<Ekos::ScriptTypes, QString> &scripts) 0170 { 0171 Ekos::ScriptsManager *manager = Ekos::Manager::Instance()->findChild<Ekos::ScriptsManager*>(); 0172 // fail if manager not found 0173 KVERIFY2_SUB(manager != nullptr, "Cannot find script manager!"); 0174 manager->setScripts(scripts); 0175 manager->done(QDialog::Accepted); 0176 return true; 0177 } 0178 0179 void TestEkosCaptureHelper::cleanupScheduler() 0180 { 0181 Ekos::Manager::Instance()->schedulerModule()->stop(); 0182 QTest::qWait(5000); 0183 // remove jobs 0184 Ekos::Manager::Instance()->schedulerModule()->removeAllJobs(); 0185 } 0186 0187 QStringList TestEkosCaptureHelper::getSimpleEsqContent(CaptureSettings settings, QVector<SimpleCaptureLightsJob> jobs, 0188 ESQVersion version) 0189 { 0190 QStringList result = serializeGeneralSettings(settings, version); 0191 0192 0193 for (QVector<SimpleCaptureLightsJob>::iterator job_iter = jobs.begin(); job_iter != jobs.end(); job_iter++) 0194 result.append(serializeJob(*job_iter, version)); 0195 0196 result.append("</SequenceQueue>"); 0197 return result; 0198 } 0199 0200 QStringList TestEkosCaptureHelper::getSimpleEsqContent(CaptureSettings settings, QVector<SimpleCaptureCalibratingJob> jobs, 0201 ESQVersion version) 0202 { 0203 QStringList result = serializeGeneralSettings(settings, version); 0204 0205 0206 for (QVector<SimpleCaptureCalibratingJob>::iterator job_iter = jobs.begin(); job_iter != jobs.end(); job_iter++) 0207 result.append(serializeJob(*job_iter, version)); 0208 0209 result.append("</SequenceQueue>"); 0210 return result; 0211 } 0212 0213 QStringList TestEkosCaptureHelper::serializeGeneralSettings(CaptureSettings settings, ESQVersion version) 0214 { 0215 QStringList result({"<?xml version=\"1.0\" encoding=\"UTF-8\"?>", 0216 QString("<SequenceQueue version='%1'><CCD>CCD Simulator</CCD>").arg(esqVersionNames[version]), 0217 "<FilterWheel>CCD Simulator</FilterWheel>", 0218 QString("<Observer>%1</Observer>").arg(settings.observer), 0219 QString("<GuideDeviation enabled='%1'>%2</GuideDeviation>").arg(settings.guideDeviation.enabled ? "true" : "false").arg(settings.guideDeviation.value), 0220 QString("<GuideStartDeviation enabled='%1'>%2</GuideStartDeviation>").arg(settings.startGuideDeviation.enabled ? "true" : "false").arg(settings.startGuideDeviation.value), 0221 QString("<Autofocus enabled='%1'>%2</Autofocus>").arg(settings.inSequenceFocus.enabled ? "true" : "false").arg(settings.inSequenceFocus.value), 0222 QString("<RefocusOnTemperatureDelta enabled='%1'>%2</RefocusOnTemperatureDelta>").arg(settings.autofocusOnTemperature.enabled ? "true" : "false").arg(settings.autofocusOnTemperature.value), 0223 QString("<RefocusEveryN enabled='%1'>%2</RefocusEveryN>").arg(settings.refocusEveryN.enabled ? "true" : "false").arg(settings.refocusEveryN.value), 0224 QString("<RefocusOnMeridianFlip enabled='%1'/>").arg(settings.refocusAfterMeridianFlip ? "true" : "false")}); 0225 0226 return result; 0227 } 0228 0229 QStringList TestEkosCaptureHelper::serializeJob(const TestEkosCaptureHelper::SimpleCaptureLightsJob &job, 0230 ESQVersion version) 0231 { 0232 QStringList result({"<Job>", 0233 QString("<Exposure>%1</Exposure>").arg(job.exposureTime), 0234 "<Format>Mono</Format>", 0235 QString("<Encoding>%1</Encoding>").arg(job.encoding), 0236 QString("<Binning><X>%1</X><Y>%2</Y></Binning>").arg(job.binX).arg(job.binY), 0237 QString("<Frame><X>%1</X><Y>%2</Y><W>%3</W><H>%4</H></Frame>").arg(job.x).arg(job.y).arg(job.w).arg(job.h), 0238 QString("<Temperature force='%2'>%1</Temperature>").arg(job.cameraTemperature.value).arg(job.cameraTemperature.enabled ? "true" : "false"), 0239 QString("<Filter>%1</Filter>").arg(job.filterName), 0240 QString("<Type>%1</Type>").arg(job.type), 0241 QString("<Count>%1</Count>").arg(job.count), 0242 QString("<Delay>%1</Delay>").arg(job.delayMS / 1000)}); 0243 switch (version) 0244 { 0245 case ESQ_VERSION_2_4: 0246 result.append(QString("<Prefix><RawPrefix>%1</RawPrefix></Prefix>").arg(job.targetName)); 0247 case ESQ_VERSION_2_5: 0248 // no target specified 0249 break; 0250 case ESQ_VERSION_2_6: 0251 result.append(QString("<TargetName>%1</TargetName>").arg(job.targetName)); 0252 break; 0253 } 0254 0255 result.append({QString("<PlaceholderFormat>%1</PlaceholderFormat>").arg(job.placeholderFormat), 0256 QString("<PlaceholderSuffix>%1</PlaceholderSuffix>").arg(job.formatSuffix), 0257 QString("<FITSDirectory>%1</FITSDirectory>").arg(job.fitsDirectory), 0258 QString("<UploadMode>%1</UploadMode>").arg(job.uploadMode), 0259 "<Properties />", 0260 "<Calibration>"}); 0261 switch (version) 0262 { 0263 case ESQ_VERSION_2_4: 0264 case ESQ_VERSION_2_5: 0265 result.append({"<FlatSource><Type>Manual</Type></FlatSource>", 0266 "<FlatDuration><Type>ADU</Type><Value>15000</Value><Tolerance>1000</Tolerance></FlatDuration>", 0267 "<PreMountPark>False</PreMountPark>", 0268 "<PreDomePark>False</PreDomePark>", 0269 "</Calibration>", 0270 "</Job>"}); 0271 break; 0272 case ESQ_VERSION_2_6: 0273 result.append({QString("<PreAction><Type>%1</Type></PreAction>").arg(0), 0274 "<FlatDuration><Type>ADU</Type><Value>15000</Value><Tolerance>1000</Tolerance></FlatDuration>", 0275 "</Calibration>", 0276 "</Job>"}); 0277 break; 0278 } 0279 return result; 0280 } 0281 0282 QStringList TestEkosCaptureHelper::serializeJob(const SimpleCaptureCalibratingJob &job, ESQVersion version) 0283 { 0284 QStringList result({"<Job>", 0285 QString("<Exposure>%1</Exposure>").arg(job.exposureTime), 0286 "<Format>Mono</Format>", 0287 QString("<Encoding>%1</Encoding>").arg("FITS"), 0288 QString("<Binning><X>%1</X><Y>%2</Y></Binning>").arg(2).arg(2), 0289 QString("<Frame><X>%1</X><Y>%2</Y><W>%3</W><H>%4</H></Frame>").arg(0).arg(0).arg(1280).arg(1080), 0290 QString("<Temperature force='%2'>%1</Temperature>").arg(-20).arg("true"), 0291 QString("<Filter>%1</Filter>").arg("Luminance"), 0292 QString("<Type>%1</Type>").arg(job.type), 0293 QString("<Count>%1</Count>").arg(job.count), 0294 QString("<Delay>%1</Delay>").arg(2), 0295 QString("<PlaceholderFormat>%1</PlaceholderFormat>").arg("/%t/%T/%F/%t_%T_%F_%e_%D"), 0296 QString("<PlaceholderSuffix>%1</PlaceholderSuffix>").arg(2), 0297 QString("<FITSDirectory>%1</FITSDirectory>").arg("/home/pi"), 0298 QString("<UploadMode>%1</UploadMode>").arg(0), 0299 "<Properties />", 0300 "<Calibration>"}); 0301 0302 0303 switch (version) 0304 { 0305 case ESQ_VERSION_2_4: 0306 case ESQ_VERSION_2_5: 0307 if (job.preAction & ACTION_WALL) 0308 { 0309 result.append("<FlatSource><Type>Wall</Type>"); 0310 result.append(QString("<Az>%1</Az>").arg(job.wall_az)); 0311 result.append(QString("<Alt>%1</Alt>").arg(job.wall_alt)); 0312 result.append(QString("</FlatSource>")); 0313 } 0314 else 0315 result.append("<FlatSource><Type>Manual</Type></FlatSource>"); 0316 0317 result.append({QString("<PreMountPark>%1</PreMountPark>").arg((job.preAction & ACTION_PARK_MOUNT) > 0 ? "True" : "False"), 0318 QString("<PreDomePark>%1</PreDomePark>").arg((job.preAction & ACTION_PARK_DOME) > 0 ? "True" : "False")}); 0319 break; 0320 0321 case ESQ_VERSION_2_6: 0322 result.append(QString("<PreAction><Type>%1</Type>").arg(job.preAction)); 0323 if (job.preAction & ACTION_WALL) 0324 result.append({QString("<Az>%1</Az>").arg(job.wall_az), 0325 QString("<Alt>%1</Alt>").arg(job.wall_alt)}); 0326 result.append("</PreAction>"); 0327 break; 0328 } 0329 result.append("<FlatDuration dark='false'>"); 0330 if (job.duration_manual) 0331 result.append("<Type>Manual</Type>"); 0332 else if (job.duration_adu) 0333 result.append(QString("<Type>ADU</Type><Value>%1</Value><Tolerance>%2</Tolerance>").arg(job.adu).arg(job.tolerance)); 0334 0335 result.append({"</FlatDuration>", 0336 "</Calibration>", 0337 "</Job>"}); 0338 0339 return result; 0340 0341 } 0342