File indexing completed on 2024-04-21 14:47:25
0001 /* 0002 Helper class of KStars UI tests 0003 0004 SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "config-kstars.h" 0010 #include "test_ekos.h" 0011 #include "test_ekos_debug.h" 0012 #include "test_ekos_simulator.h" 0013 #include "ekos/guide/guide.h" 0014 #include "ekos/manager/meridianflipstate.h" 0015 0016 #include "indi/indidevice.h" 0017 #include "indi/indigroup.h" 0018 #include "indi/indidome.h" 0019 #include "indi/indiproperty.h" 0020 #include "indi/indielement.h" 0021 #include "indi/guimanager.h" 0022 #include "oal/oal.h" 0023 #include "ekos/scheduler/scheduler.h" 0024 0025 #include <QObject> 0026 0027 #pragma once 0028 0029 /** 0030 * @brief Helper function to verify the execution of a statement. 0031 * 0032 * If the result is false, this function immediately returns with false, 0033 * otherwise simply continues. 0034 * Use this function in subroutines of test cases which should return bool. 0035 * @param statement expression to be verified 0036 * @return false if statement equals false, otherwise continuing 0037 */ 0038 #define KVERIFY_SUB(statement) \ 0039 do {\ 0040 if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\ 0041 return false;\ 0042 } while (false) 0043 0044 /** 0045 * @brief Subroutine version of QVERIFY2 0046 * @return false if statement equals false, otherwise continuing 0047 */ 0048 #define KVERIFY2_SUB(statement, description) \ 0049 do {\ 0050 if (statement) {\ 0051 if (!QTest::qVerify(true, #statement, (description), __FILE__, __LINE__))\ 0052 return false;\ 0053 } else {\ 0054 if (!QTest::qVerify(false, #statement, (description), __FILE__, __LINE__))\ 0055 return false;\ 0056 }\ 0057 } while (false) 0058 0059 /** 0060 * @brief Helper macro to wrap statements with test macros that returns false if 0061 * the given statement preliminary invokes return (due to a test failure inside). 0062 * @return false if statement equals false, otherwise continuing 0063 */ 0064 #define KWRAP_SUB(statement) \ 0065 { bool passed = false; \ 0066 [&]() { statement; passed = true;}(); \ 0067 if (!passed) return false; \ 0068 } while (false); 0069 0070 /** 0071 * @brief Subroutine version of QTRY_TIMEOUT_DEBUG_IMPL 0072 * @return false if expression equals false, otherwise continuing 0073 */ 0074 #define KTRY_TIMEOUT_DEBUG_IMPL_SUB(expr, timeoutValue, step)\ 0075 if (!(expr)) { \ 0076 QTRY_LOOP_IMPL((expr), (2 * timeoutValue), step);\ 0077 if (expr) { \ 0078 QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time."); \ 0079 msg = msg.arg(QString::fromUtf8(#expr)).arg(timeoutValue).arg(timeoutValue + qt_test_i); \ 0080 KVERIFY2_SUB(false, qPrintable(msg)); \ 0081 } \ 0082 } 0083 0084 /** 0085 * @brief Subroutine version of QTRY_IMPL 0086 * @return false if expression equals false, otherwise continuing 0087 */ 0088 #define KTRY_IMPL_SUB(expr, timeout)\ 0089 const int qt_test_step = 50; \ 0090 const int qt_test_timeoutValue = timeout; \ 0091 QTRY_LOOP_IMPL((expr), qt_test_timeoutValue, qt_test_step); \ 0092 KTRY_TIMEOUT_DEBUG_IMPL_SUB((expr), qt_test_timeoutValue, qt_test_step)\ 0093 0094 /** 0095 * @brief Subroutine version of QTRY_VERIFY_WITH_TIMEOUT 0096 * @param expr expression to be verified 0097 * @param timeout max time until the expression must become true 0098 * @return false if statement equals false, otherwise continuing 0099 */ 0100 #define KTRY_VERIFY_WITH_TIMEOUT_SUB(expr, timeout) \ 0101 do { \ 0102 KTRY_IMPL_SUB((expr), timeout);\ 0103 KVERIFY_SUB(expr); \ 0104 } while (false) 0105 0106 /** @brief Helper to retrieve a gadget from a certain module view. 0107 * @param module KStars module that holds the checkox 0108 * @param klass is the class of the gadget to look for. 0109 * @param name is the gadget name to look for in the UI configuration. 0110 * @warning Fails the test if the gadget "name" of class "klass" does not exist in the Mount module 0111 */ 0112 #define KTRY_GADGET(module, klass, name) klass * const name = module->findChild<klass*>(#name); \ 0113 QTRY_VERIFY2_WITH_TIMEOUT(name != nullptr, QString(#klass " '%1' does not exist and cannot be used").arg(#name).toStdString().c_str(), 10000) 0114 0115 /** @brief Helper to retrieve a gadget from a certain module view (subroutine version). 0116 * @param module KStars module that holds the checkox 0117 * @param klass is the class of the gadget to look for. 0118 * @param name is the gadget name to look for in the UI configuration. 0119 * @warning Fails the test if the gadget "name" of class "klass" does not exist in the Mount module 0120 */ 0121 #define KTRY_GADGET_SUB(module, klass, name) klass * const name = module->findChild<klass*>(#name); \ 0122 KVERIFY2_SUB(name != nullptr, QString(#klass " '%1' does not exist and cannot be used").arg(#name).toStdString().c_str()) 0123 0124 /** @brief Retrieve an INDI element from the INDI controller 0125 * @param device INDI device name 0126 * @param group INDI group within the device 0127 * @param name INDI property name within the group 0128 * @param property resulting INDI property (@see #INDI_P) 0129 */ 0130 #define KTRY_INDI_PROPERTY(device, group, name, property) INDI_P * property = nullptr; \ 0131 do { \ 0132 INDI_D *indi_device = GUIManager::Instance()->findGUIDevice(device); \ 0133 QVERIFY(indi_device != nullptr); \ 0134 INDI_G *indi_group = indi_device->getGroup(group); \ 0135 QVERIFY(indi_group != nullptr); \ 0136 property = indi_group->getProperty(name); \ 0137 } while (false); \ 0138 QVERIFY(property != nullptr); 0139 0140 /** @brief Helper to find a top level window with a given title 0141 * @param result resulting object name 0142 * @param name window name 0143 */ 0144 #define KTRY_FIND_WINDOW(result, name) \ 0145 QWindow * result = nullptr; \ 0146 for (QWindow *window : qApp->topLevelWindows()) { \ 0147 if (window->title() == name) { \ 0148 result = window; break; } \ 0149 } \ 0150 QVERIFY(result != nullptr); QTRY_VERIFY_WITH_TIMEOUT(result->isVisible(), 1000); \ 0151 0152 0153 /** @brief Helper to click a button from a certain module view. 0154 * @param module KStars module that holds the checkox 0155 * @param button is the gadget name of the button to look for in the UI configuration. 0156 * @warning Fails the test if the button is not currently enabled. 0157 */ 0158 #define KTRY_CLICK(module, button) do { \ 0159 QTimer::singleShot(100, Ekos::Manager::Instance(), [&]() { \ 0160 KTRY_GADGET(module, QPushButton, button); \ 0161 QVERIFY2(button->isEnabled(), QString("QPushButton '%1' is disabled and cannot be clicked").arg(#button).toStdString().c_str()); \ 0162 QTest::mouseClick(button, Qt::LeftButton); }); \ 0163 QTest::qWait(200); } while(false) 0164 0165 /** @brief Helper to click a button from a certain module view (subroutine version for KTRY_CLICK). 0166 * @param module KStars module that holds the checkox 0167 * @param button is the gadget name of the button to look for in the UI configuration. 0168 * @warning Fails the test if the button is not currently enabled. 0169 */ 0170 #define KTRY_CLICK_SUB(module, button) do { \ 0171 bool success = false; \ 0172 QTimer::singleShot(100, Ekos::Manager::Instance(), [&]() { \ 0173 KTRY_GADGET(module, QPushButton, button); \ 0174 QVERIFY2(button->isEnabled(), QString("QPushButton '%1' is disabled and cannot be clicked").arg(#button).toStdString().c_str()); \ 0175 QTest::mouseClick(button, Qt::LeftButton); success = true;}); \ 0176 KTRY_VERIFY_WITH_TIMEOUT_SUB(success, 1000);} while(false) 0177 0178 /** @brief Helper to set a checkbox and verify whether it succeeded 0179 * @param module KStars module that holds the checkox 0180 * @param checkbox object name of the checkbox 0181 * @param value value the checkbox should be set 0182 */ 0183 #define KTRY_SET_CHECKBOX(module, checkbox, value) \ 0184 KTRY_GADGET(module, QCheckBox, checkbox); checkbox->setChecked(value); QVERIFY(checkbox->isChecked() == value) 0185 0186 /** @brief Subroutine version of @see KTRY_SET_CHECKBOX 0187 * @param module KStars module that holds the checkox 0188 * @param checkbox object name of the checkbox 0189 * @param value value the checkbox should be set 0190 */ 0191 #define KTRY_SET_CHECKBOX_SUB(module, checkbox, value) \ 0192 KWRAP_SUB(KTRY_SET_CHECKBOX(module, checkbox, value)) 0193 0194 /** @brief Helper to set a radiobutton and verify whether it succeeded 0195 * @param module KStars module that holds the radiobutton 0196 * @param checkbox object name of the radiobutton 0197 * @param value value the radiobutton should be set 0198 */ 0199 #define KTRY_SET_RADIOBUTTON(module, radiobutton, value) \ 0200 KTRY_GADGET(module, QRadioButton, radiobutton); radiobutton->setChecked(value); QVERIFY(radiobutton->isChecked() == value) 0201 0202 /** @brief Subroutine version of @see KTRY_SET_RADIOBUTTON 0203 * @param module KStars module that holds the radiobutton 0204 * @param checkbox object name of the radiobutton 0205 * @param value value the radiobutton should be set 0206 */ 0207 #define KTRY_SET_RADIOBUTTON_SUB(module, radiobutton, value) \ 0208 KWRAP_SUB(KTRY_SET_RADIOBUTTON(module, radiobutton, value)) 0209 0210 /** @brief Helper to set a spinbox and verify whether it succeeded 0211 * @param module KStars module that holds the spinbox 0212 * @param spinbox object name of the spinbox 0213 * @param value value the spinbox should be set 0214 */ 0215 #define KTRY_SET_SPINBOX(module, spinbox, x) \ 0216 KTRY_GADGET(module, QSpinBox, spinbox); spinbox->setValue(x); QVERIFY(spinbox->value() == x) 0217 0218 /** @brief Subroutine version of @see KTRY_SET_SPINBOX 0219 * @param module KStars module that holds the spinbox 0220 * @param spinbox object name of the spinbox 0221 * @param value value the spinbox should be set 0222 */ 0223 #define KTRY_SET_SPINBOX_SUB(module, spinbox, x) \ 0224 KWRAP_SUB(KTRY_SET_SPINBOX(module, spinbox, x)) 0225 0226 /** @brief Helper to set a doublespinbox and verify whether it succeeded 0227 * @param module KStars module that holds the spinbox 0228 * @param spinbox object name of the spinbox 0229 * @param value value the spinbox should be set 0230 */ 0231 #define KTRY_SET_DOUBLESPINBOX(module, spinbox, x) \ 0232 KTRY_GADGET(module, QDoubleSpinBox, spinbox); spinbox->setValue(x); QVERIFY((spinbox->value() - x < 0.001)) 0233 0234 /** @brief Subroutine version of @see KTRY_SET_DOUBLESPINBOX_SUB 0235 * @param module KStars module that holds the spinbox 0236 * @param spinbox object name of the spinbox 0237 * @param value value the spinbox should be set 0238 */ 0239 #define KTRY_SET_DOUBLESPINBOX_SUB(module, spinbox, x) \ 0240 KWRAP_SUB(KTRY_SET_DOUBLESPINBOX(module, spinbox, x)) 0241 0242 /** @brief Helper to set a combo box and verify whether it succeeded 0243 * @param module KStars module that holds the combo box 0244 * @param combo object name of the combo box 0245 * @param value value the combo box should be set 0246 */ 0247 #define KTRY_SET_COMBO(module, combo, value) \ 0248 KTRY_GADGET(module, QComboBox, combo); combo->setCurrentText(value); QTRY_VERIFY_WITH_TIMEOUT(combo->currentText() == value, 1000) 0249 0250 /** @brief Helper to set a combo box by index and verify whether it succeeded 0251 * @param module KStars module that holds the combo box 0252 * @param combo object name of the combo box 0253 * @param value index the combo box should be selected 0254 */ 0255 #define KTRY_SET_COMBO_INDEX(module, combo, value) \ 0256 KTRY_GADGET(module, QComboBox, combo); combo->setCurrentIndex(value); QVERIFY(combo->currentIndex() == value) 0257 0258 /** @brief Subroutine version of @see KTRY_SET_COMBO 0259 * @param module KStars module that holds the combo box 0260 * @param combo object name of the combo box 0261 * @param value value the combo box should be set 0262 */ 0263 #define KTRY_SET_COMBO_SUB(module, combo, value) \ 0264 KWRAP_SUB(KTRY_GADGET(module, QComboBox, combo); combo->setCurrentText(value); QVERIFY(combo->currentText() == value)) 0265 0266 /** @brief Helper to set a combo box by index and verify whether it succeeded 0267 * @param module KStars module that holds the combo box 0268 * @param combo object name of the combo box 0269 * @param value index the combo box should be selected 0270 */ 0271 #define KTRY_SET_COMBO_INDEX_SUB(module, combo, value) \ 0272 KWRAP_SUB(KTRY_SET_COMBO_INDEX(module, combo, value)) 0273 0274 /** @brief Helper to set a line edit box and verify whether it succeeded 0275 * @param module KStars module that holds the line edit box 0276 * @param spinbox object name of the line edit box 0277 * @param value value the line edit box should be set 0278 */ 0279 #define KTRY_SET_LINEEDIT(module, lineedit, value) \ 0280 KTRY_GADGET(module, QLineEdit, lineedit); lineedit->setText(value); QVERIFY((lineedit->text() == value)) 0281 0282 /** @brief Subroutine version of @see KTRY_SET_LINEEDIT 0283 * @param module KStars module that holds the line edit box 0284 * @param spinbox object name of the line edit box 0285 * @param value value the line edit box should be set 0286 */ 0287 #define KTRY_SET_LINEEDIT_SUB(module, lineedit, value) \ 0288 KWRAP_SUB(KTRY_GADGET(module, QLineEdit, lineedit); lineedit->setText(value); QVERIFY((lineedit->text() == value))) 0289 0290 /** 0291 * @brief Helper to check whether a state queue is empty after the given delay 0292 * @param queue event queue 0293 * @param delay in milliseconds 0294 */ 0295 #define KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(queue, delay) \ 0296 if (! QTest::qWaitFor([&](){return queue.isEmpty();}, delay)) { \ 0297 QString result("States not reached: "); \ 0298 QTextStream stream(&result); \ 0299 while (!(queue).isEmpty()) stream << (queue).dequeue(); \ 0300 QFAIL(qPrintable(result));} 0301 0302 /** 0303 * @brief Helper to check whether a state queue is empty after the given delay 0304 * @param queue event queue 0305 * @param delay in milliseconds 0306 */ 0307 #define KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT_SUB(queue, delay) \ 0308 if (! QTest::qWaitFor([&](){return queue.isEmpty();}, delay)) { \ 0309 QString result("States not reached: "); \ 0310 QTextStream stream(&result); \ 0311 while (!(queue).isEmpty()) stream << (queue).dequeue(); \ 0312 QWARN(qPrintable(result)); return false;} 0313 0314 /** 0315 * @brief Helper to verify if the text in the text field starts with the given text 0316 * @param field UI Text field 0317 * @param text Text the text field should start with 0318 * @param timeout in ms 0319 */ 0320 #define KTRY_VERIFY_TEXTFIELD_STARTS_WITH_TIMEOUT_SUB(field, title, timeout) \ 0321 KTRY_VERIFY_WITH_TIMEOUT_SUB(field->text().length() >= QString(title).length() && \ 0322 field->text().left(QString(title).length()).compare(title) == 0, timeout) 0323 0324 /** 0325 * @brief Helper function for switching to a certain module 0326 * @param module target module 0327 * @param timeout in ms 0328 */ 0329 #define KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(module, timeout) do {\ 0330 KTRY_EKOS_GADGET(QTabWidget, toolsWidget); \ 0331 toolsWidget->setCurrentWidget(module); \ 0332 QTRY_COMPARE_WITH_TIMEOUT(toolsWidget->currentWidget(), module, timeout);} while (false) 0333 0334 #define SET_INDI_VALUE_DOUBLE(device, group, property, value) do {\ 0335 int result = QProcess::execute(QString("indi_setprop"), {QString("-n"), QString("%1.%2.%3=%4").arg(device).arg(group).arg(property).arg(value)});\ 0336 qCInfo(KSTARS_EKOS_TEST) << "Process result code: " << result;\ 0337 } while (false) 0338 0339 #define SET_INDI_VALUE_SWITCH(device, group, property, value) do {\ 0340 int result = QProcess::execute(QString("indi_setprop"), {QString("-s"), QString("%1.%2.%3=%4").arg(device).arg(group).arg(property).arg(value==true?"On":"Off")});\ 0341 qCInfo(KSTARS_EKOS_TEST) << "Process result code: " << result;\ 0342 } while (false) 0343 0344 #define CLOSE_MODAL_DIALOG(button_nr) do { \ 0345 QTimer::singleShot(1000, capture, [&]() { \ 0346 QDialog * const dialog = qobject_cast <QDialog*> (QApplication::activeModalWidget()); \ 0347 if (dialog) \ 0348 { \ 0349 QList<QPushButton*> pb = dialog->findChildren<QPushButton*>(); \ 0350 QTest::mouseClick(pb[button_nr], Qt::MouseButton::LeftButton); \ 0351 qCInfo(KSTARS_EKOS_TEST) << "Button clicked:" << button_nr; \ 0352 } \ 0353 else \ 0354 qCWarning(KSTARS_EKOS_TEST) << "No active modal widget found!" ; \ 0355 }); \ 0356 } while (false) 0357 0358 0359 0360 class TestEkosHelper : public QObject 0361 { 0362 Q_OBJECT 0363 public: 0364 explicit TestEkosHelper(QString guider = nullptr); 0365 0366 // main optical train 0367 QString m_primaryTrain = i18n("Primary"); 0368 QString m_guidingTrain = i18n("Secondary"); 0369 0370 // predefined set of scopes 0371 OAL::Scope *fsq85, *newton_10F4, *takfinder10x50; 0372 enum ScopeType {SCOPE_FSQ85, SCOPE_NEWTON_10F4, SCOPE_TAKFINDER10x50}; 0373 // map scope type to predefined scope 0374 OAL::Scope *getScope(ScopeType type); 0375 0376 // Mount device 0377 QString m_MountDevice = ""; 0378 // CCD device 0379 QString m_CCDDevice = ""; 0380 // Rotator device 0381 QString m_RotatorDevice = ""; 0382 // Guiding device 0383 QString m_GuiderDevice = ""; 0384 // Focusing device 0385 QString m_FocuserDevice = ""; 0386 // Flat light panel device 0387 QString m_LightPanelDevice = ""; 0388 // Dust cap device 0389 QString m_DustCapDevice = ""; 0390 // Dome device 0391 QString m_DomeDevice = ""; 0392 0393 // Guider (PHD2 or Internal) 0394 QString m_Guider = "Internal"; 0395 0396 // PHD2 setup (host and port) 0397 QProcess *phd2 { nullptr }; 0398 QString const phd2_guider_host = "localhost"; 0399 QString const phd2_guider_port = "4400"; 0400 0401 // guiding used? 0402 bool use_guiding = false; 0403 // did a dithering start? 0404 bool dithered = false; 0405 0406 // sequence of alignment states that are expected 0407 QQueue<Ekos::AlignState> expectedAlignStates; 0408 // sequence of capture states that are expected 0409 QQueue<Ekos::CaptureState> expectedCaptureStates; 0410 // sequence of focus states that are expected 0411 QQueue<Ekos::FocusState> expectedFocusStates; 0412 // sequence of guiding states that are expected 0413 QQueue<Ekos::GuideState> expectedGuidingStates; 0414 // sequence of mount states that are expected 0415 QQueue<ISD::Mount::Status> expectedMountStates; 0416 // sequence of dome states that are expected 0417 QQueue<ISD::Dome::Status> expectedDomeStates; 0418 // sequence of meridian flip states that are expected 0419 QQueue<Ekos::MeridianFlipState::MeridianFlipMountState> expectedMeridianFlipStates; 0420 // sequence of scheduler states that are expected 0421 QQueue<Ekos::SchedulerState> expectedSchedulerStates; 0422 0423 /** 0424 * @brief Initialization ahead of executing the test cases. 0425 */ 0426 void virtual init(); 0427 0428 /** 0429 * @brief Cleanup after test cases have been executed. 0430 */ 0431 void virtual cleanup(); 0432 0433 /** 0434 * @brief Fill mount, guider, CCD and focuser of an EKOS profile 0435 * @param isDone will be true if everything succeeds 0436 */ 0437 void fillProfile(bool *isDone); 0438 0439 /** 0440 * @brief create a new EKOS profile 0441 * @param name name of the profile 0442 * @param isPHD2 use internal guider or PHD2 0443 * @param isDone will be true if everything succeeds 0444 */ 0445 void createEkosProfile(QString name, bool isPHD2, bool *isDone); 0446 0447 /** 0448 * @brief Configure the EKOS profile 0449 * @param name of the profile 0450 * @param isPHD2 use internal guider or PHD2 0451 */ 0452 bool setupEkosProfile(QString name, bool isPHD2); 0453 0454 /** 0455 * @brief Start a test EKOS profile. 0456 */ 0457 bool startEkosProfile(); 0458 0459 /** 0460 * @brief Shutdown the current test EKOS profile. 0461 */ 0462 bool shutdownEkosProfile(); 0463 0464 0465 /** 0466 * @brief Helper function starting PHD2 0467 */ 0468 void startPHD2(); 0469 0470 /** 0471 * @brief Helper function stopping PHD2 0472 */ 0473 void stopPHD2(); 0474 0475 /** 0476 * @brief Helper function for preparing the PHD2 test configuration 0477 */ 0478 void preparePHD2(); 0479 0480 /** 0481 * @brief Helper function for cleaning up PHD2 test configuration 0482 */ 0483 void cleanupPHD2(); 0484 0485 /** 0486 * @brief Prepare two optical trains for test purposes, one for capturing and one for guiding 0487 */ 0488 void prepareOpticalTrains(); 0489 0490 /** 0491 * @brief Helper function that ensures that alignment works in a test environment 0492 */ 0493 void prepareAlignmentModule(); 0494 0495 /** 0496 * @brief Helper function that ensures that capturing works in a test environment 0497 */ 0498 void prepareCaptureModule(); 0499 0500 /** 0501 * @brief Helper function that ensures that focusing works in a test environment 0502 */ 0503 void prepareFocusModule(); 0504 0505 /** 0506 * @brief Helper function that ensures that guiding works in a test environment 0507 */ 0508 void prepareGuidingModule(); 0509 0510 /** 0511 * @brief Prepare the mount module with the given mount parameters 0512 */ 0513 void prepareMountModule(ScopeType primary = SCOPE_FSQ85, ScopeType guiding = SCOPE_TAKFINDER10x50); 0514 0515 /** 0516 * @brief Slew to a given position 0517 * @param fast set to true if slewing should be fast using sync first close to the position 0518 */ 0519 bool slewTo(double RA, double DEC, bool fast); 0520 0521 /** 0522 * @brief Helper function for start of guiding 0523 * @param guiding exposure time 0524 */ 0525 bool startGuiding(double expTime); 0526 0527 /** 0528 * @brief Helper function to stop guiding 0529 */ 0530 bool stopGuiding(); 0531 0532 /** 0533 * @brief Start alignment process 0534 * @param expTime exposure time 0535 * @return true iff starting alignment succeeds 0536 */ 0537 bool startAligning(double expTime); 0538 0539 /** 0540 * @brief Check if astrometry files exist. 0541 * @return true iff astrometry files found 0542 */ 0543 bool checkAstrometryFiles(); 0544 0545 /** 0546 * @brief Returns true iff astrometry is available and checks if necessary. 0547 */ 0548 bool isAstrometryAvailable(); 0549 0550 /** 0551 * @brief Helper function for focusing 0552 * @param initialFocusPosition starting point for focusing 0553 */ 0554 bool executeFocusing(int initialFocusPosition = 40000); 0555 0556 /** 0557 * @brief Helper function to stop focusing 0558 */ 0559 bool stopFocusing(); 0560 0561 /** 0562 * @brief Determine the number of seconds until the meridian flip should take place by reading 0563 * the displayed meridian flip status. 0564 * @param message text containing the seconds to the meridian flip 0565 */ 0566 int secondsToMF(QString message); 0567 0568 /** 0569 * @brief update J2000 coordinates 0570 */ 0571 void updateJ2000Coordinates(SkyPoint *target); 0572 0573 /** 0574 * @brief Set a tree view combo to a given value 0575 * @param combo box with tree view 0576 * @param lookup target value 0577 */ 0578 void setTreeviewCombo(QComboBox *combo, const QString lookup); 0579 0580 /** 0581 * @brief Simple write-string-to-file utility. 0582 * @param filename name of the file to be created 0583 * @param lines file content 0584 */ 0585 bool writeFile(const QString &filename, const QStringList &lines, 0586 QFileDevice::Permissions permissions = QFileDevice::ReadOwner | QFileDevice::WriteOwner); 0587 0588 /** 0589 * @brief createCountingScript create a script that reads the number from its log file, 0590 * increases it by 1 and outputs it to the logfile. With this script we can count 0591 * how often it has been executed. 0592 * @param scriptname full path to the script file 0593 * @param logfilename full path to the log file the script will produce 0594 * @return true iff file creation succeeds 0595 */ 0596 bool createCountingScript(Ekos::ScriptTypes, const QString scriptname); 0597 0598 /** 0599 * @brief createAllCaptureScripts Create all pre-/post job/capture scripts 0600 * @param directory where the scripts should be located 0601 */ 0602 bool createAllCaptureScripts(QTemporaryDir *destination); 0603 0604 /** 0605 * @brief countScriptRuns Utility that extracts the number of test script runs from its log file. 0606 * @param scripttype script type, its name will be extracted from {@see #scripts} 0607 * @return counter from the log file 0608 */ 0609 int countScriptRuns(Ekos::ScriptTypes scripttype); 0610 0611 /** 0612 * @brief checkScriptRuns Check if the configured pre- and post scripts have been running correctly 0613 * @param captures_per_sequence number of captures per sequence (all sequences must have the identical 0614 * number) 0615 * @param sequences number of capture sequences 0616 */ 0617 bool checkScriptRuns(int captures_per_sequence, int sequences); 0618 0619 /** 0620 * @brief Retrieve the current alignment status. 0621 */ 0622 inline Ekos::AlignState getAlignStatus() 0623 { 0624 return m_AlignStatus; 0625 } 0626 /** 0627 * @brief Retrieve the current capture status. 0628 */ 0629 inline Ekos::CaptureState getCaptureStatus() 0630 { 0631 return m_CaptureStatus; 0632 } 0633 /** 0634 * @brief Retrieve the current focus status. 0635 */ 0636 inline Ekos::FocusState getFocusStatus() 0637 { 0638 return m_FocusStatus; 0639 } 0640 /** 0641 * @brief Retrieve the current guiding status. 0642 */ 0643 Ekos::GuideState getGuidingStatus() 0644 { 0645 return m_GuideStatus; 0646 } 0647 /** 0648 * @brief Retrieve the current guide deviation 0649 */ 0650 double getGuideDeviation() 0651 { 0652 return m_GuideDeviation; 0653 } 0654 /** 0655 * @brief Retrieve the current mount meridian flip status. 0656 */ 0657 Ekos::MeridianFlipState::MeridianFlipMountState getMeridianFlipStatus() 0658 { 0659 return m_MFStatus; 0660 } 0661 /** 0662 * @brief Retrieve the current scheduler status. 0663 */ 0664 Ekos::SchedulerState getSchedulerStatus() 0665 { 0666 return m_SchedulerStatus; 0667 } 0668 /** 0669 * @brief Retrieve the current dome status. 0670 */ 0671 ISD::Dome::Status getDomeStatus() 0672 { 0673 return m_DomeStatus; 0674 } 0675 0676 const QMap<Ekos::ScriptTypes, QString> &getScripts() const 0677 { 0678 return scripts; 0679 } 0680 /** 0681 * @brief Connect to read all modules state changes 0682 */ 0683 void connectModules(); 0684 0685 /** 0686 * @brief Search for a certain scope in the database and create it if necessary 0687 * @param model scope model 0688 * @param vendor scope vendor 0689 * @param type scope type (refractor, newton, ... 0690 * @param aperture scope aperture in mm 0691 * @param focallenght focal length in mm 0692 * @return scope object 0693 */ 0694 OAL::Scope *createScopeIfNecessary(QString model, QString vendor, QString type, double aperture, double focallenght); 0695 0696 private: 0697 // current mount status 0698 ISD::Mount::Status m_MountStatus { ISD::Mount::MOUNT_IDLE }; 0699 0700 // current mount meridian flip status 0701 Ekos::MeridianFlipState::MeridianFlipMountState m_MFStatus { Ekos::MeridianFlipState::MOUNT_FLIP_NONE }; 0702 0703 // current alignment status 0704 Ekos::AlignState m_AlignStatus { Ekos::ALIGN_IDLE }; 0705 0706 // current capture status 0707 Ekos::CaptureState m_CaptureStatus { Ekos::CAPTURE_IDLE }; 0708 0709 // current focus status 0710 Ekos::FocusState m_FocusStatus { Ekos::FOCUS_IDLE }; 0711 0712 // current guiding status 0713 Ekos::GuideState m_GuideStatus { Ekos::GUIDE_IDLE }; 0714 0715 // current dome status 0716 ISD::Dome::Status m_DomeStatus { ISD::Dome::DOME_IDLE }; 0717 0718 // current guiding deviation 0719 double m_GuideDeviation { -1 }; 0720 0721 // current scheduler status 0722 Ekos::SchedulerState m_SchedulerStatus { Ekos::SCHEDULER_IDLE }; 0723 0724 // pre- and post sequence / capture execution scripts 0725 QMap<Ekos::ScriptTypes, QString> scripts; 0726 0727 /** 0728 * @brief Slot to track the align status of the mount 0729 * @param status new align state 0730 */ 0731 void alignStatusChanged(Ekos::AlignState status); 0732 0733 /** 0734 * @brief Slot to track the mount status 0735 * @param status new mount status 0736 */ 0737 void mountStatusChanged(ISD::Mount::Status status); 0738 0739 /** 0740 * @brief Slot to track the meridian flip stage of the mount 0741 * @param status new meridian flip state 0742 */ 0743 void meridianFlipStatusChanged(Ekos::MeridianFlipState::MeridianFlipMountState status); 0744 0745 /** 0746 * @brief Slot to track the focus status 0747 * @param status new focus status 0748 */ 0749 void focusStatusChanged(Ekos::FocusState status); 0750 0751 /** 0752 * @brief Slot to track the guiding status 0753 * @param status new guiding status 0754 */ 0755 void guidingStatusChanged(Ekos::GuideState status); 0756 0757 /** 0758 * @brief Slot to track guiding deviation events 0759 * @param delta_ra RA deviation 0760 * @param delta_dec DEC deviation 0761 */ 0762 void guideDeviationChanged(double delta_ra, double delta_dec); 0763 0764 /** 0765 * @brief Slot to track the capture status 0766 * @param status new capture status 0767 */ 0768 void captureStatusChanged(Ekos::CaptureState status); 0769 0770 /** 0771 * @brief Slot to track the scheduler status 0772 * @param status new scheduler status 0773 */ 0774 void schedulerStatusChanged(Ekos::SchedulerState status); 0775 0776 /** 0777 * @brief Slot to track the dome status 0778 * @param status new scheduler status 0779 */ 0780 void domeStatusChanged(ISD::Dome::Status status); 0781 0782 private: 0783 bool m_astrometry_available; 0784 0785 };