File indexing completed on 2024-03-24 15:18:39

0001 /*  KStars UI tests
0002     SPDX-FileCopyrightText: 2020 Eric Dejouhanet <eric.dejouhanet@gmail.com>
0003     Fabrizio Pollastri <mxgbot@gmail.com> 2020-08-30
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef TESTEKOSMOUNT_H
0009 #define TESTEKOSMOUNT_H
0010 
0011 #include "config-kstars.h"
0012 #include "test_ekos.h"
0013 #include "ekos/mount/mount.h"
0014 
0015 #if defined(HAVE_INDI)
0016 #include "indicom.h"
0017 
0018 #include <QObject>
0019 #include <QPushButton>
0020 #include <QComboBox>
0021 #include <QDoubleSpinBox>
0022 #include <QSpinBox>
0023 #include <QCheckBox>
0024 #include <QTest>
0025 #include <QDialog>
0026 
0027 /** @brief Helper to retrieve a gadget in the Mount tab specifically.
0028  * @param klass is the class of the gadget to look for.
0029  * @param name is the gadget name to look for in the UI configuration.
0030  * @warning Fails the test if the gadget "name" of class "klass" does not exist in the Mount module
0031  */
0032 #define KTRY_MOUNT_GADGET(klass, name) klass * const name = Ekos::Manager::Instance()->mountModule()->findChild<klass*>(#name); \
0033     QVERIFY2(name != nullptr, QString(#klass " '%1' does not exist and cannot be used").arg(#name).toStdString().c_str())
0034 
0035 /** @brief Helper to click a button in the Mount tab specifically.
0036  * @param button is the gadget name of the button to look for in the UI configuration.
0037  * @warning Fails the test if the button is not currently enabled.
0038  */
0039 #define KTRY_MOUNT_CLICK(button) do { \
0040     QTimer::singleShot(100, Ekos::Manager::Instance(), []() { \
0041         KTRY_MOUNT_GADGET(QPushButton, button); \
0042         QVERIFY2(button->isEnabled(), QString("QPushButton '%1' is disabled and cannot be clicked").arg(#button).toStdString().c_str()); \
0043         QTest::mouseClick(button, Qt::LeftButton); }); \
0044     QTest::qWait(200); } while(false)
0045 
0046 /** @brief Helper to sync the mount to an object.
0047  * @param name is the name of the object to sync to.
0048  * @param track whether to enable track or not.
0049  */
0050 #define KTRY_MOUNT_SYNC_NAMED(name, track) do { \
0051     QVERIFY(KStars::Instance()); \
0052     QVERIFY(KStars::Instance()->data()); \
0053     SkyObject const * const so = KStars::Instance()->data()->objectNamed(name); \
0054     QVERIFY(so != nullptr); \
0055     QVERIFY(KStarsData::Instance()); \
0056     GeoLocation * const geo = KStarsData::Instance()->geo(); \
0057     KStarsDateTime const now(KStarsData::Instance()->lt()); \
0058     KSNumbers const numbers(now.djd()); \
0059     CachingDms const LST = geo->GSTtoLST(geo->LTtoUT(now).gst()); \
0060     QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule() != nullptr, 5000); \
0061     Ekos::Manager::Instance()->mountModule()->setMeridianFlipValues(true, 0); \
0062     QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->unpark(), 5000); \
0063     SkyObject o(*so); \
0064     o.updateCoordsNow(&numbers); \
0065     o.EquatorialToHorizontal(&LST, geo->lat()); \
0066     QVERIFY(Ekos::Manager::Instance()->mountModule()->sync(o.ra().Hours(), o.dec().Degrees())); \
0067     if (!track) \
0068         QTimer::singleShot(1000, [&]{ \
0069         QDialog * const dialog = qobject_cast <QDialog*> (QApplication::activeModalWidget()); \
0070         if(dialog != nullptr) emit dialog->accept(); }); \
0071     Ekos::Manager::Instance()->mountModule()->setTrackEnabled(track); \
0072     if (track) \
0073         QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->status() == ISD::Mount::Status::MOUNT_TRACKING, 30000); \
0074     } while (false)
0075 
0076 /** @brief Helper to sync the mount at the meridian for focus tests.
0077  * @warning This is needed because the CCD Simulator has much rotation jitter at the celestial pole.
0078  * @param alt is the altitude to sync to, use 60.0 as degrees for instance.
0079  * @param track whether to enable track or not.
0080  * @param ha_ofs is the offset to add to the LST before syncing (east is positive).
0081  */
0082 #define KTRY_MOUNT_SYNC(alt, track, ha_ofs) do { \
0083     QVERIFY(KStarsData::Instance()); \
0084     GeoLocation * const geo = KStarsData::Instance()->geo(); \
0085     KStarsDateTime const now(KStarsData::Instance()->lt()); \
0086     KSNumbers const numbers(now.djd()); \
0087     CachingDms const LST = geo->GSTtoLST(geo->LTtoUT(now).gst()); \
0088     QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule() != nullptr, 5000); \
0089     Ekos::Manager::Instance()->mountModule()->setMeridianFlipValues(true, 0); \
0090     QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->unpark(), 5000); \
0091     QVERIFY(Ekos::Manager::Instance()->mountModule()->sync(range24(LST.Hours()+(ha_ofs+0.002)), (alt))); \
0092     QVERIFY(Ekos::Manager::Instance()->mountModule()->slew(range24(LST.Hours()+(ha_ofs)), (alt))); \
0093     if (!track) \
0094         QTimer::singleShot(1000, [&]{ \
0095         QDialog * const dialog = qobject_cast <QDialog*> (QApplication::activeModalWidget()); \
0096         if(dialog != nullptr) emit dialog->accept(); }); \
0097     Ekos::Manager::Instance()->mountModule()->setTrackEnabled(track); \
0098     if (track) \
0099         QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->status() == ISD::Mount::Status::MOUNT_TRACKING, 30000); \
0100     } while (false)
0101 
0102 class TestEkosMount : public QObject
0103 {
0104     Q_OBJECT
0105 
0106 public:
0107     explicit TestEkosMount(QObject *parent = nullptr);
0108 
0109 private slots:
0110     void initTestCase();
0111     void cleanupTestCase();
0112 
0113     void init();
0114     void cleanup();
0115 
0116     void testMountCtrlCoordLabels();
0117     void testMountCtrlCoordConversion();
0118     void testMountCtrlGoto();
0119     void testMountCtrlSync();
0120 
0121 private:
0122     Ekos::Manager *ekos;
0123     QWindow *mountControl;
0124     QObject *raLabel, *deLabel, *raText, *deText,
0125         *coordRaDe, *coordAzAl, *coordHaDe,
0126         *raValue, *deValue, *azValue, *altValue, *haValue, *zaValue,
0127         *gotoButton, *syncButton;
0128     double degreePrecision = 2 * 1.0 / 3600.0;
0129     double hourPrecision = 2 * 15.0 / 3600.0;
0130 
0131 
0132 };
0133 
0134 #endif // HAVE_INDI
0135 #endif // TESTEKOSMOUNT_H