9#include "ksmessagebox.h"
10#include "driverinfo.h"
14#include "skymapcomposite.h"
15#include "ksnotification.h"
17#include <KActionCollection>
20#include <QtDBus/qdbusmetatype.h>
22#include <indi_debug.h>
30const QList<KLocalizedString> Mount::mountStates = {
ki18n(
"Idle"),
ki18n(
"Moving"),
ki18n(
"Slewing"),
38 centerLockTimer.setInterval(5000);
39 centerLockTimer.setSingleShot(
true);
47 updateCoordinatesTimer.setInterval(1000);
48 updateCoordinatesTimer.setSingleShot(
false);
53 currentCoords.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->
geo()->lat());
54 emit newCoords(currentCoords, pierSide(), hourAngle());
58 qRegisterMetaType<ISD::Mount::Status>(
"ISD::Mount::Status");
59 qDBusRegisterMetaType<ISD::Mount::Status>();
61 qRegisterMetaType<ISD::Mount::PierSide>(
"ISD::Mount::PierSide");
62 qDBusRegisterMetaType<ISD::Mount::PierSide>();
70void Mount::registerProperty(INDI::Property prop)
72 if (prop.isNameMatch(
"TELESCOPE_INFO"))
74 auto ti = prop.getNumber();
79 bool aperture_ok =
false, focal_ok =
false;
82 auto aperture = ti->findWidgetByName(
"TELESCOPE_APERTURE");
83 if (aperture && aperture->getValue() <= 0)
85 if (getDriverInfo()->getAuxInfo().contains(
"TELESCOPE_APERTURE"))
87 temp = getDriverInfo()->getAuxInfo().value(
"TELESCOPE_APERTURE").toDouble(&aperture_ok);
90 aperture->setValue(temp);
91 auto g_aperture = ti->findWidgetByName(
"GUIDER_APERTURE");
92 if (g_aperture && g_aperture->getValue() <= 0)
93 g_aperture->setValue(aperture->getValue());
98 auto focal_length = ti->findWidgetByName(
"TELESCOPE_FOCAL_LENGTH");
99 if (focal_length && focal_length->getValue() <= 0)
101 if (getDriverInfo()->getAuxInfo().contains(
"TELESCOPE_FOCAL_LENGTH"))
103 temp = getDriverInfo()->getAuxInfo().value(
"TELESCOPE_FOCAL_LENGTH").toDouble(&focal_ok);
106 focal_length->setValue(temp);
107 auto g_focal = ti->findWidgetByName(
"GUIDER_FOCAL_LENGTH");
108 if (g_focal && g_focal->getValue() <= 0)
109 g_focal->setValue(focal_length->getValue());
114 if (aperture_ok && focal_ok)
117 else if (prop.isNameMatch(
"ON_COORD_SET"))
119 m_canGoto = IUFindSwitch(prop.getSwitch(),
"TRACK") !=
nullptr;
120 m_canSync = IUFindSwitch(prop.getSwitch(),
"SYNC") !=
nullptr;
121 m_canFlip = IUFindSwitch(prop.getSwitch(),
"FLIP") !=
nullptr;
123 else if (prop.isNameMatch(
"TELESCOPE_PIER_SIDE"))
125 auto svp = prop.getSwitch();
126 int currentSide = svp->findOnSwitchIndex();
127 if (currentSide != m_PierSide)
129 m_PierSide =
static_cast<PierSide
>(currentSide);
130 emit pierSideChanged(m_PierSide);
133 else if (prop.isNameMatch(
"TELESCOPE_PARK"))
135 else if (prop.isNameMatch(
"TELESCOPE_TRACK_STATE"))
136 m_canControlTrack =
true;
137 else if (prop.isNameMatch(
"TELESCOPE_TRACK_MODE"))
139 m_hasTrackModes =
true;
140 auto svp = prop.getSwitch();
141 for (
int i = 0; i < svp->count(); i++)
143 if (svp->at(i)->isNameMatch(
"TRACK_SIDEREAL"))
144 TrackMap[TRACK_SIDEREAL] = i;
145 else if (svp->at(i)->isNameMatch(
"TRACK_SOLAR"))
146 TrackMap[TRACK_SOLAR] = i;
147 else if (svp->at(i)->isNameMatch(
"TRACK_LUNAR"))
148 TrackMap[TRACK_LUNAR] = i;
149 else if (svp->at(i)->isNameMatch(
"TRACK_CUSTOM"))
150 TrackMap[TRACK_CUSTOM] = i;
153 else if (prop.isNameMatch(
"TELESCOPE_TRACK_RATE"))
154 m_hasCustomTrackRate =
true;
155 else if (prop.isNameMatch(
"TELESCOPE_ABORT_MOTION"))
157 else if (prop.isNameMatch(
"TELESCOPE_PARK_OPTION"))
158 m_hasCustomParking =
true;
159 else if (prop.isNameMatch(
"TELESCOPE_SLEW_RATE"))
161 m_hasSlewRates =
true;
162 auto svp = prop.getSwitch();
166 for (
const auto &it : *svp)
167 m_slewRates << it.getLabel();
170 else if (prop.isNameMatch(
"EQUATORIAL_EOD_COORD"))
173 m_hasEquatorialCoordProperty =
true;
175 else if (prop.isNameMatch(
"SAT_TRACKING_STAT"))
177 m_canTrackSatellite =
true;
179 else if (prop.isNameMatch(
"EQUATORIAL_COORD"))
182 m_hasEquatorialCoordProperty =
true;
198 currentObject = KStarsData::Instance()->skyComposite()->objectNearest(¤tCoords, maxrad);
207void Mount::processNumber(INDI::Property prop)
209 auto nvp = prop.getNumber();
210 if (nvp->isNameMatch(
"EQUATORIAL_EOD_COORD") || nvp->isNameMatch(
"EQUATORIAL_COORD"))
212 auto RA = nvp->findWidgetByName(
"RA");
213 auto DEC = nvp->findWidgetByName(
"DEC");
215 if (RA ==
nullptr || DEC ==
nullptr)
221 currentCoords.
setRA0(RA->value);
222 currentCoords.
setDec0(DEC->value);
227 currentCoords.
setRA(RA->value);
228 currentCoords.
setDec(DEC->value);
237 if (! updateCoordinatesTimer.isActive())
238 updateCoordinatesTimer.start();
241 auto currentStatus = status(nvp);
243 if (nvp->getState() == IPS_BUSY && EqCoordPreviousState != IPS_BUSY)
245 if (currentStatus == MOUNT_SLEWING)
246 KSNotification::event(QLatin1String(
"SlewStarted"),
i18n(
"Mount is slewing to target location"), KSNotification::Mount);
248 else if (EqCoordPreviousState == IPS_BUSY && nvp->getState() == IPS_OK &&
slewDefined())
250 if (Options::useExternalSkyMap())
261 KSNotification::event(QLatin1String(
"SlewCompleted"),
i18n(
"Mount arrived at target location"), KSNotification::Mount);
265 EqCoordPreviousState = nvp->getState();
273 else if (nvp->isNameMatch(
"HORIZONTAL_COORD") && m_hasEquatorialCoordProperty ==
false)
275 auto Az = nvp->findWidgetByName(
"AZ");
276 auto Alt = nvp->findWidgetByName(
"ALT");
278 if (Az ==
nullptr || Alt ==
nullptr)
281 currentCoords.setAz(Az->value);
282 currentCoords.setAlt(Alt->value);
290 if (! updateCoordinatesTimer.isActive())
291 updateCoordinatesTimer.start();
295 else if (nvp->isNameMatch(
"POLLING_PERIOD"))
298 auto period = nvp->findWidgetByName(
"PERIOD_MS");
299 if (period !=
nullptr)
300 updateCoordinatesTimer.setInterval(
static_cast<int>(period->getValue()));
305void Mount::processSwitch(INDI::Property prop)
307 bool manualMotionChanged =
false;
308 auto svp = prop.getSwitch();
310 if (svp->isNameMatch(
"CONNECTION"))
312 auto conSP = svp->findWidgetByName(
"CONNECT");
318 if (conSP->getState() == ISS_ON)
323 centerLockTimer.stop();
327 else if (svp->isNameMatch(
"TELESCOPE_PARK"))
329 else if (svp->isNameMatch(
"TELESCOPE_ABORT_MOTION"))
331 if (svp->s == IPS_OK)
333 inCustomParking =
false;
334 KSNotification::event(QLatin1String(
"MountAborted"),
i18n(
"Mount motion was aborted"), KSNotification::Mount,
335 KSNotification::Warn);
338 else if (svp->isNameMatch(
"TELESCOPE_PIER_SIDE"))
340 int currentSide = IUFindOnSwitchIndex(svp);
341 if (currentSide != m_PierSide)
343 m_PierSide =
static_cast<PierSide
>(currentSide);
344 emit pierSideChanged(m_PierSide);
347 else if (svp->isNameMatch(
"TELESCOPE_TRACK_MODE"))
349 auto sp = svp->findOnSwitch();
352 if (sp->isNameMatch(
"TRACK_SIDEREAL"))
353 currentTrackMode = TRACK_SIDEREAL;
354 else if (sp->isNameMatch(
"TRACK_SOLAR"))
355 currentTrackMode = TRACK_SOLAR;
356 else if (sp->isNameMatch(
"TRACK_LUNAR"))
357 currentTrackMode = TRACK_LUNAR;
359 currentTrackMode = TRACK_CUSTOM;
362 else if (svp->isNameMatch(
"TELESCOPE_MOTION_NS"))
363 manualMotionChanged =
true;
364 else if (svp->isNameMatch(
"TELESCOPE_MOTION_WE"))
365 manualMotionChanged =
true;
366 else if (svp->isNameMatch(
"TELESCOPE_REVERSE_MOTION"))
368 emit axisReversed(AXIS_DE, svp->at(0)->getState() == ISS_ON);
369 emit axisReversed(AXIS_RA, svp->at(1)->getState() == ISS_ON);
372 if (manualMotionChanged)
374 auto NSCurrentMotion =
getSwitch(
"TELESCOPE_MOTION_NS")->getState();
375 auto WECurrentMotion =
getSwitch(
"TELESCOPE_MOTION_WE")->getState();
376 inCustomParking =
false;
377 inManualMotion = (NSCurrentMotion == IPS_BUSY || WECurrentMotion == IPS_BUSY);
381void Mount::processText(INDI::Property prop)
383 auto tvp = prop.getText();
384 if (tvp->isNameMatch(
"SAT_TLE_TEXT"))
386 if ((tvp->getState() == IPS_OK) && (m_TLEIsSetForTracking))
388 auto trajWindow =
getText(
"SAT_PASS_WINDOW");
391 qCDebug(KSTARS_INDI) <<
"Property SAT_PASS_WINDOW not found";
395 auto trajStart = trajWindow->findWidgetByName(
"SAT_PASS_WINDOW_START");
396 auto trajEnd = trajWindow->findWidgetByName(
"SAT_PASS_WINDOW_END");
398 if (!trajStart || !trajEnd)
400 qCDebug(KSTARS_INDI) <<
"Start or end in SAT_PASS_WINDOW not found";
404 trajStart->setText(g_satPassStart.toString(
Qt::ISODate).toLocal8Bit().data());
405 trajEnd->setText(g_satPassEnd.toString(
Qt::ISODate).toLocal8Bit().data());
408 m_windowIsSetForTracking =
true;
413 else if (tvp->isNameMatch(
"SAT_PASS_WINDOW"))
415 if ((tvp->getState() == IPS_OK) && (m_TLEIsSetForTracking) && (m_windowIsSetForTracking))
417 auto trackSwitchV =
getSwitch(
"SAT_TRACKING_STAT");
420 qCDebug(KSTARS_INDI) <<
"Property SAT_TRACKING_STAT not found";
424 auto trackSwitch = trackSwitchV->findWidgetByName(
"SAT_TRACK");
427 trackSwitchV->reset();
428 trackSwitch->setState(ISS_ON);
431 m_TLEIsSetForTracking =
false;
432 m_windowIsSetForTracking =
false;
445 auto sp = svp->findWidgetByName(
"PARK");
448 if (svp->getState() == IPS_ALERT)
451 emit newParkStatus(PARK_ERROR);
454 m_ParkStatus = (sp->getState() == ISS_ON) ? PARK_PARKED : PARK_UNPARKED;
455 KSNotification::event(
QLatin1String(
"MountParkingFailed"),
i18n(
"Mount parking failed"), KSNotification::Mount,
456 KSNotification::Alert);
458 else if (svp->getState() == IPS_BUSY && sp->s == ISS_ON && m_ParkStatus != PARK_PARKING)
460 m_ParkStatus = PARK_PARKING;
461 KSNotification::event(
QLatin1String(
"MountParking"),
i18n(
"Mount parking is in progress"), KSNotification::Mount);
462 currentObject =
nullptr;
464 emit newParkStatus(m_ParkStatus);
466 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_OFF && m_ParkStatus != PARK_UNPARKING)
468 m_ParkStatus = PARK_UNPARKING;
469 KSNotification::event(
QLatin1String(
"MountUnParking"),
i18n(
"Mount unparking is in progress"), KSNotification::Mount);
471 emit newParkStatus(m_ParkStatus);
473 else if (svp->getState() == IPS_OK && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKED)
475 m_ParkStatus = PARK_PARKED;
476 KSNotification::event(
QLatin1String(
"MountParked"),
i18n(
"Mount parked"), KSNotification::Mount);
477 currentObject =
nullptr;
479 emit newParkStatus(m_ParkStatus);
491 else if ( (svp->getState() == IPS_OK || svp->getState() == IPS_IDLE) && sp->getState() == ISS_OFF
492 && m_ParkStatus != PARK_UNPARKED)
494 m_ParkStatus = PARK_UNPARKED;
495 KSNotification::event(
QLatin1String(
"MountUnparked"),
i18n(
"Mount unparked"), KSNotification::Mount);
496 currentObject =
nullptr;
498 emit newParkStatus(m_ParkStatus);
509bool Mount::canGuide()
511 auto raPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_WE");
512 auto decPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_NS");
514 return raPulse && decPulse;
519 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
524 auto parkSW = parkSP->findWidgetByName(
"PARK");
526 return (parkSW !=
nullptr);
529bool Mount::isSlewing()
531 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
536 return (EqProp->getState() == IPS_BUSY);
539bool Mount::isInMotion()
541 return (isSlewing() || inManualMotion);
544bool Mount::doPulse(GuideDirection ra_dir,
int ra_msecs, GuideDirection dec_dir,
int dec_msecs)
546 if (canGuide() ==
false)
549 bool raOK = doPulse(ra_dir, ra_msecs);
550 bool decOK = doPulse(dec_dir, dec_msecs);
552 return raOK && decOK;
555bool Mount::doPulse(GuideDirection dir,
int msecs)
557 auto raPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_WE");
558 auto decPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_NS");
559 INDI::PropertyView<INumber> *npulse =
nullptr;
560 INDI::WidgetView<INumber> *dirPulse =
nullptr;
562 if (!raPulse || !decPulse)
569 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_W");
574 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_E");
579 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_N");
584 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_S");
594 dirPulse->setValue(msecs);
602void Mount::setCustomParking(SkyPoint * coords)
605 if (coords ==
nullptr)
610 inCustomParking = rc;
616 double maxrad = 1000.0 / Options::zoomFactor();
621void Mount::centerLock()
623 if (Options::isTracking() ==
false ||
630 Options::setIsTracking(
true);
632 centerLockTimer.start();
635void Mount::centerUnlock()
638 centerLockTimer.stop();
643 double currentRA = 0, currentDEC = 0, currentAlt = 0, currentAz = 0;
644 bool useJ2000 {
false}, useEquatorialCoordinates {
false}, useHorizontalCoordinates {
false};
648 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
650 if (!EqProp.isValid() || EqProp.getPermission() == IP_RO)
653 auto J2000EQNP = getNumber(
"EQUATORIAL_COORD");
654 if (J2000EQNP.isValid() && EqProp.getPermission() != IP_RO)
657 useEquatorialCoordinates =
true;
662 useEquatorialCoordinates =
true;
665 auto HorProp = getNumber(
"HORIZONTAL_COORD");
666 if (HorProp.isValid() && HorProp.getPermission() != IP_RO)
667 useHorizontalCoordinates =
true;
671 if (useEquatorialCoordinates)
673 currentRA = EqProp.findWidgetByName(
"RA")->getValue();
674 currentDEC = EqProp.findWidgetByName(
"DEC")->getValue();
679 if (useHorizontalCoordinates)
681 currentAz = HorProp.findWidgetByName(
"AZ")->getValue();
682 currentAlt = HorProp.findWidgetByName(
"ALT")->getValue();
686 if (useEquatorialCoordinates ==
false && useHorizontalCoordinates ==
false)
691 auto sendToMountDevice = [ = ]()
705 if (useEquatorialCoordinates)
714 ScopeTarget->
setRA0(ScopeTarget->
ra());
717 ra = ScopeTarget->
ra();
718 de = ScopeTarget->
dec();
722 ra = ScopeTarget->
ra0();
723 de = ScopeTarget->
dec0();
728 ra = ScopeTarget->
ra();
729 de = ScopeTarget->
dec();
732 EqProp.findWidgetByName(
"RA")->setValue(ra.
Hours());
733 EqProp.findWidgetByName(
"DEC")->setValue(de.
Degrees());
736 qCDebug(KSTARS_INDI) <<
"ISD:Telescope sending coords RA:" << ra.
toHMSString() <<
"DE:" << de.
toDMSString();
738 EqProp.findWidgetByName(
"RA")->setValue(currentRA);
739 EqProp.findWidgetByName(
"DEC")->setValue(currentDEC);
742 else if (useHorizontalCoordinates)
744 HorProp.findWidgetByName(
"AZ")->setValue(ScopeTarget->
az().
Degrees());
745 HorProp.findWidgetByName(
"ALT")->setValue(ScopeTarget->
alt().
Degrees());
747 HorProp.findWidgetByName(
"AZ")->setValue(currentAz);
748 HorProp.findWidgetByName(
"ALT")->setValue(currentAlt);
757 auto checkObjectAndSend = [ = ]()
761 currentObject = KStarsData::Instance()->skyComposite()->objectNearest(ScopeTarget, maxrad);
764 auto checkTrackModes = [ = ]()
769 if (currentObject->type() == SkyObject::MOON)
771 if (currentTrackMode != TRACK_LUNAR && TrackMap.contains(TRACK_LUNAR))
772 setTrackMode(TrackMap.value(TRACK_LUNAR));
775 else if (currentObject->name() ==
i18n(
"Sun"))
777 if (currentTrackMode != TRACK_SOLAR && TrackMap.contains(TRACK_SOLAR))
778 setTrackMode(TrackMap.value(TRACK_SOLAR));
783 else if (currentTrackMode == TRACK_SOLAR || currentTrackMode == TRACK_LUNAR)
784 setTrackMode(TRACK_SIDEREAL);
790 if (currentObject->name() ==
i18n(
"Sun") && currentTrackMode != TRACK_SOLAR)
794 KSMessageBox::Instance()->disconnect(
this);
800 KSMessageBox::Instance()->disconnect(
this);
803 KSMessageBox::Instance()->questionYesNo(
804 i18n(
"Warning! Looking at the Sun without proper protection can lead to irreversible eye damage!"),
805 i18n(
"Sun Warning"));
820 if ((-90 <= minAlt && maxAlt <= 90) && (targetAlt < minAlt || targetAlt > maxAlt) && !altLimitsTrackingOnly)
823 i18n(
"Requested altitude %1 is outside the specified altitude limit boundary (%2,%3).",
825 QString::number(maxAlt,
'g', 3)), KSNotification::Mount, KSNotification::Warn);
826 qCInfo(KSTARS_INDI) <<
"Requested altitude " <<
QString::number(targetAlt,
'g', 3)
827 <<
" is outside the specified altitude limit boundary ("
833 if (Options::confirmBelowHorizon() && targetAlt < 0 && minAlt == -1)
837 if (minAlt < -90 && +90 < maxAlt)
838 Options::setConfirmBelowHorizon(
false);
839 KSMessageBox::Instance()->disconnect(
this);
840 checkObjectAndSend();
844 KSMessageBox::Instance()->disconnect(
this);
845 if (useEquatorialCoordinates)
847 EqProp.findWidgetByName(
"RA")->setValue(currentRA);
848 EqProp.findWidgetByName(
"DEC")->setValue(currentDEC);
850 if (useHorizontalCoordinates)
852 HorProp.findWidgetByName(
"AZ")->setValue(currentAz);
853 HorProp.findWidgetByName(
"ALT")->setValue(currentAlt);
857 KSMessageBox::Instance()->questionYesNo(
i18n(
"Requested altitude is below the horizon. Are you sure you want to proceed?"),
858 i18n(
"Telescope Motion"), 15,
false);
861 checkObjectAndSend();
868 auto motionSP =
getSwitch(
"ON_COORD_SET");
870 if (!motionSP.isValid())
874 auto sp = motionSP.findOnSwitch();
876 (sp->name == std::string(
"TRACK") ||
877 sp->name == std::string(
"SLEW") ||
878 sp->name == std::string(
"FLIP")))
888bool Mount::Slew(
double ra,
double dec,
bool flip)
903 return Slew(&target, flip);
906bool Mount::Slew(SkyPoint * ScopeTarget,
bool flip)
908 auto motionSP =
getSwitch(
"ON_COORD_SET");
913 auto slewSW = flip ? motionSP->findWidgetByName(
"FLIP") : motionSP->findWidgetByName(
"TRACK");
915 if (flip && (!slewSW))
916 slewSW = motionSP->findWidgetByName(
"TRACK");
919 slewSW = motionSP->findWidgetByName(
"SLEW");
924 if (slewSW->getState() != ISS_ON)
927 slewSW->setState(ISS_ON);
930 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: " << slewSW->getName();
936bool Mount::Sync(
double ra,
double dec)
943 return Sync(&target);
946bool Mount::Sync(SkyPoint * ScopeTarget)
948 auto motionSP =
getSwitch(
"ON_COORD_SET");
953 auto syncSW = motionSP->findWidgetByName(
"SYNC");
958 if (syncSW->getState() != ISS_ON)
961 syncSW->setState(ISS_ON);
964 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Syncing...";
972 auto motionSP =
getSwitch(
"TELESCOPE_ABORT_MOTION");
977 auto abortSW = motionSP->findWidgetByName(
"ABORT");
982 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Aborted." <<
Qt::endl;
984 abortSW->setState(ISS_ON);
987 inCustomParking =
false;
994 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
999 auto parkSW = parkSP->findWidgetByName(
"PARK");
1004 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Parking..." <<
Qt::endl;
1007 parkSW->setState(ISS_ON);
1015 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1020 auto parkSW = parkSP->findWidgetByName(
"UNPARK");
1025 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: UnParking..." <<
Qt::endl;
1028 parkSW->setState(ISS_ON);
1034bool Mount::getEqCoords(
double * ra,
double * dec)
1036 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
1039 EqProp = getNumber(
"EQUATORIAL_COORD");
1044 auto RAEle = EqProp->findWidgetByName(
"RA");
1048 auto DecEle = EqProp->findWidgetByName(
"DEC");
1052 *ra = RAEle->getValue();
1053 *
dec = DecEle->getValue();
1058bool Mount::MoveNS(VerticalMotion dir, MotionCommand cmd)
1060 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1065 auto motionNorth = motionSP->findWidgetByName(
"MOTION_NORTH");
1066 auto motionSouth = motionSP->findWidgetByName(
"MOTION_SOUTH");
1068 if (!motionNorth || !motionSouth)
1072 if (dir == MOTION_NORTH && motionNorth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1075 if (dir == MOTION_SOUTH && motionSouth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1080 if (cmd == MOTION_START)
1082 if (dir == MOTION_NORTH)
1083 motionNorth->setState(ISS_ON);
1085 motionSouth->setState(ISS_ON);
1095 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1109 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1121bool Mount::MoveWE(HorizontalMotion dir, MotionCommand cmd)
1123 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1128 auto motionWest = motionSP->findWidgetByName(
"MOTION_WEST");
1129 auto motionEast = motionSP->findWidgetByName(
"MOTION_EAST");
1131 if (!motionWest || !motionEast)
1135 if (dir == MOTION_WEST && motionWest->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1138 if (dir == MOTION_EAST && motionEast->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1143 if (cmd == MOTION_START)
1145 if (dir == MOTION_WEST)
1146 motionWest->setState(ISS_ON);
1148 motionEast->setState(ISS_ON);
1156bool Mount::setSlewRate(
int index)
1158 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1163 if (index < 0 || index > slewRateSP->count())
1165 else if (slewRateSP->findOnSwitchIndex() == index)
1168 slewRateSP->reset();
1170 slewRateSP->at(index)->setState(ISS_ON);
1174 emit slewRateChanged(index);
1179int Mount::getSlewRate()
const
1181 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1186 return slewRateSP->findOnSwitchIndex();
1189void Mount::setAltLimits(
double minAltitude,
double maxAltitude,
bool trackingOnly)
1191 minAlt = minAltitude;
1192 maxAlt = maxAltitude;
1193 altLimitsTrackingOnly = trackingOnly;
1196bool Mount::setAlignmentModelEnabled(
bool enable)
1198 bool wasExecuted =
false;
1201 auto alignSwitch =
getSwitch(
"ALIGNMENT_SUBSYSTEM_ACTIVE");
1204 alignSwitch->at(0)->setState(enable ? ISS_ON : ISS_OFF);
1213 alignSwitch->reset();
1216 alignSwitch->at(2)->setState(ISS_ON);
1219 alignSwitch->at(0)->setState(ISS_ON);
1230 auto tleTextVec =
getText(
"SAT_TLE_TEXT");
1233 qCDebug(KSTARS_INDI) <<
"Property SAT_TLE_TEXT not found";
1237 auto tleText = tleTextVec->findWidgetByName(
"TLE");
1244 m_TLEIsSetForTracking =
true;
1245 g_satPassStart = satPassStart;
1246 g_satPassEnd = satPassEnd;
1252bool Mount::clearParking()
1254 auto parkSwitch =
getSwitch(
"TELESCOPE_PARK_OPTION");
1258 auto clearParkSW = parkSwitch->findWidgetByName(
"PARK_PURGE_DATA");
1262 parkSwitch->reset();
1263 clearParkSW->setState(ISS_ON);
1269bool Mount::clearAlignmentModel()
1271 bool wasExecuted =
false;
1274 auto clearSwitch =
getSwitch(
"ALIGNMENT_POINTSET_ACTION");
1275 auto commitSwitch =
getSwitch(
"ALIGNMENT_POINTSET_COMMIT");
1276 if (clearSwitch && commitSwitch)
1278 clearSwitch->reset();
1280 clearSwitch->at(4)->setState(ISS_ON);
1282 commitSwitch->at(0)->setState(ISS_ON);
1292 clearSwitch->reset();
1293 clearSwitch->at(1)->setState(ISS_ON);
1301Mount::Status Mount::status()
1303 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
1304 if (EqProp ==
nullptr)
1306 EqProp = getNumber(
"EQUATORIAL_COORD");
1307 if (EqProp ==
nullptr)
1311 return status(EqProp);
1314const QString Mount::statusString(Mount::Status status,
bool translated)
const
1318 case ISD::Mount::MOUNT_MOVING:
1319 return (translated ? mountStates[status].
toString() : mountStates[status].untranslatedText() + QString(
" %1").arg(
1320 getManualMotionString()));
1322 return translated ? mountStates[status].toString() : mountStates[status].untranslatedText();
1326QString Mount::getManualMotionString()
const
1328 QString NSMotion, WEMotion;
1330 auto movementSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1333 if (movementSP->at(MOTION_NORTH)->getState() == ISS_ON)
1335 else if (movementSP->at(MOTION_SOUTH)->getState() == ISS_ON)
1339 movementSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1342 if (movementSP->at(MOTION_WEST)->getState() == ISS_ON)
1344 else if (movementSP->at(MOTION_EAST)->getState() == ISS_ON)
1348 return QString(
"%1%2").arg(NSMotion, WEMotion);
1351bool Mount::setTrackEnabled(
bool enable)
1353 auto trackSP =
getSwitch(
"TELESCOPE_TRACK_STATE");
1357 auto trackON = trackSP->findWidgetByName(
"TRACK_ON");
1358 auto trackOFF = trackSP->findWidgetByName(
"TRACK_OFF");
1360 if (!trackON || !trackOFF)
1363 trackON->setState(enable ? ISS_ON : ISS_OFF);
1364 trackOFF->setState(enable ? ISS_OFF : ISS_ON);
1371bool Mount::isTracking()
1373 return (status() == MOUNT_TRACKING);
1376bool Mount::setTrackMode(uint8_t index)
1378 auto trackModeSP =
getSwitch(
"TELESCOPE_TRACK_MODE");
1382 if (index >= trackModeSP->nsp)
1385 trackModeSP->reset();
1386 trackModeSP->at(index)->setState(ISS_ON);
1393bool Mount::getTrackMode(uint8_t &index)
1395 auto trackModeSP =
getSwitch(
"TELESCOPE_TRACK_MODE");
1399 index = trackModeSP->findOnSwitchIndex();
1404bool Mount::setCustomTrackRate(
double raRate,
double deRate)
1406 auto trackRateNP = getNumber(
"TELESCOPE_TRACK_RATE");
1410 auto raRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_RA");
1411 auto deRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_DE");
1413 if (!raRateN || !deRateN)
1416 raRateN->setValue(raRate);
1417 deRateN->setValue(deRate);
1424bool Mount::getCustomTrackRate(
double &raRate,
double &deRate)
1426 auto trackRateNP = getNumber(
"TELESCOPE_TRACK_RATE");
1430 auto raRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_RA");
1431 auto deRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_DE");
1433 if (!raRateN || !deRateN)
1436 raRate = raRateN->getValue();
1437 deRate = deRateN->getValue();
1443bool Mount::sendParkingOptionCommand(ParkOptionCommand command)
1445 auto parkOptionsSP =
getSwitch(
"TELESCOPE_PARK_OPTION");
1449 parkOptionsSP->reset();
1450 parkOptionsSP->at(command)->setState(ISS_ON);
1456Mount::Status Mount::status(INumberVectorProperty * nvp)
1458 Status newMountStatus = MOUNT_ERROR;
1463 newMountStatus = MOUNT_MOVING;
1464 else if (isParked())
1465 newMountStatus = MOUNT_PARKED;
1467 newMountStatus = MOUNT_IDLE;
1472 newMountStatus = MOUNT_MOVING;
1473 else if (inCustomParking)
1475 inCustomParking =
false;
1477 sendParkingOptionCommand(PARK_OPTION_CURRENT);
1479 sendParkingOptionCommand(PARK_OPTION_WRITE_DATA);
1481 newMountStatus = MOUNT_TRACKING;
1484 newMountStatus = MOUNT_TRACKING;
1489 newMountStatus = MOUNT_MOVING;
1492 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1493 if (parkSP && parkSP->getState() == IPS_BUSY)
1494 newMountStatus = MOUNT_PARKING;
1496 newMountStatus = MOUNT_SLEWING;
1501 inCustomParking =
false;
1502 newMountStatus = MOUNT_ERROR;
1505 if (previousMountStatus != newMountStatus)
1508 previousMountStatus = newMountStatus;
1509 return newMountStatus;
1514 dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
1515 return dms(lst.
Degrees() - currentCoords.ra().Degrees());
1518bool Mount::isReversed(INDI_EQ_AXIS axis)
1520 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1524 return reversed->at(axis == AXIS_DE ? 0 : 1)->getState() == ISS_ON;
1527bool Mount::setReversedEnabled(INDI_EQ_AXIS axis,
bool enabled)
1529 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1533 reversed->at(axis == AXIS_DE ? 0 : 1)->setState(enabled ? ISS_ON : ISS_OFF);
1540 updateCoordinatesTimer.stop();
1541 centerLockTimer.stop();
1549 argument << static_cast<int>(source);
1560 dest =
static_cast<ISD::Mount::Status
>(a);
1567 argument << static_cast<int>(source);
1578 dest =
static_cast<ISD::Mount::PierSide
>(a);
The ConcreteDevice class.
void sendNewProperty(INDI::Property prop)
Send new property command to server.
INDI::PropertyText getText(const QString &name) const
INDI::PropertySwitch getSwitch(const QString &name) const
GenericDevice is the Generic Device for INDI devices.
void updateTarget()
updateTarget update target position from {
void newStatus(ISD::Mount::Status status)
Change in the mount status.
bool slewDefined()
Check whether sending new coordinates will result into a slew.
const dms hourAngle() const
Hour angle of the current coordinates.
void updateJ2000Coordinates(SkyPoint *coords)
Helper function to update the J2000 coordinates of a sky point from its JNow coordinates.
bool sendCoords(SkyPoint *ScopeTarget)
Send the coordinates to the mount's INDI driver.
bool setSatelliteTLEandTrack(QString tle, const KStarsDateTime satPassStart, const KStarsDateTime satPassEnd)
Tracks satellite on provided TLE, initial epoch for trajectory calculation and window in minutes.
void updateParkStatus()
updateParkStatus Updating parking status by checking the TELESCOPE_PARK property.
void stopTimers()
stopTimers Stop timers to prevent timing race condition when device is unavailable and timer is still...
void newTarget(SkyPoint ¤tCoords)
The mount has finished the slew to a new target.
void newTargetName(const QString &name)
The mount has finished the slew to a new target.
Q_INVOKABLE QAction * action(const QString &name) const
SkyMapComposite * skyComposite()
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
static KStars * Instance()
void slotSetTelescopeEnabled(bool enable)
slotSetTelescopeEnabled call when telescope comes online or goes offline.
virtual KActionCollection * actionCollection() const
SkyObject * objectNearest(SkyPoint *p, double &maxrad) override
SkyPoint * focus()
Retrieve the Focus point; the position on the sky at the center of the skymap.
void setDestination(const SkyPoint &f)
sets the destination point of the sky map.
void setFocusObject(SkyObject *o)
Set the FocusObject pointer to the argument.
void setFocusPoint(SkyPoint *f)
set the FocusPoint; the position that is to be the next Destination.
The sky coordinates of a point in the sky.
void apparentCoord(long double jd0, long double jdf)
Computes the apparent coordinates for this SkyPoint for any epoch, accounting for the effects of prec...
const CachingDms & dec() const
const CachingDms & ra0() const
void setDec(dms d)
Sets Dec, the current Declination.
void setRA(dms &r)
Sets RA, the current Right Ascension.
const CachingDms & ra() const
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
void setRA0(dms r)
Sets RA0, the catalog Right Ascension.
const CachingDms & dec0() const
void setDec0(dms d)
Sets Dec0, the catalog Declination.
SkyPoint catalogueCoord(long double jdf)
Computes the J2000.0 catalogue coordinates for this SkyPoint using the epoch removing aberration,...
An angle, stored as degrees, but expressible in many ways.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
const double & Degrees() const
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
ISD is a collection of INDI Standard Devices.
GeoCoordinates geo(const QVariant &location)
QCA_EXPORT QVariant getProperty(const QString &name)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString number(double n, char format, int precision)
QByteArray toLocal8Bit() const const
QTextStream & dec(QTextStream &stream)
QTextStream & endl(QTextStream &stream)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isValid() const const