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>
35Mount::Mount(GenericDevice *parent) : ConcreteDevice(parent)
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;
186void Mount::updateJ2000Coordinates(SkyPoint *coords)
188 SkyPoint J2000Coord(coords->ra(), coords->dec());
190 coords->setRA0(J2000Coord.ra());
191 coords->setDec0(J2000Coord.dec());
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);
223 currentCoords.apparentCoord(
static_cast<long double>(J2000),
KStars::Instance()->data()->ut().djd());
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 INumber *RAEle =
nullptr;
644 INumber *DecEle =
nullptr;
645 INumber *AzEle =
nullptr;
646 INumber *AltEle =
nullptr;
647 double currentRA = 0, currentDEC = 0, currentAlt = 0, currentAz = 0;
648 bool useJ2000(
false);
650 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
654 EqProp = getNumber(
"EQUATORIAL_COORD");
659 auto HorProp = getNumber(
"HORIZONTAL_COORD");
661 if (EqProp && EqProp->getPermission() == IP_RO)
664 if (HorProp && HorProp->getPermission() == IP_RO)
671 RAEle = EqProp->findWidgetByName(
"RA");
675 DecEle = EqProp->findWidgetByName(
"DEC");
682 currentRA = RAEle->value;
683 currentDEC = DecEle->value;
685 ScopeTarget->EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
690 AzEle = IUFindNumber(HorProp,
"AZ");
693 AltEle = IUFindNumber(HorProp,
"ALT");
697 currentAz = AzEle->value;
698 currentAlt = AltEle->value;
702 if (EqProp ==
nullptr && HorProp ==
nullptr)
707 auto sendToMountDevice = [ = ]()
728 if (ScopeTarget->dec0().Degrees() == 180.0)
730 ScopeTarget->setRA0(ScopeTarget->ra());
731 ScopeTarget->setDec0(ScopeTarget->dec());
733 ra = ScopeTarget->ra();
734 de = ScopeTarget->dec();
738 ra = ScopeTarget->ra0();
739 de = ScopeTarget->dec0();
744 ra = ScopeTarget->ra();
745 de = ScopeTarget->dec();
748 RAEle->value = ra.Hours();
749 DecEle->value = de.Degrees();
752 qCDebug(KSTARS_INDI) <<
"ISD:Telescope sending coords RA:" << ra.toHMSString() <<
753 "(" << RAEle->value <<
") DE:" << de.toDMSString() <<
754 "(" << DecEle->value <<
")";
756 RAEle->value = currentRA;
757 DecEle->value = currentDEC;
762 AzEle->value = ScopeTarget->az().Degrees();
763 AltEle->value = ScopeTarget->alt().Degrees();
765 AzEle->value = currentAz;
766 AltEle->value = currentAlt;
775 auto checkObjectAndSend = [ = ]()
782 auto checkTrackModes = [ = ]()
787 if (currentObject->
type() == SkyObject::MOON)
789 if (currentTrackMode != TRACK_LUNAR && TrackMap.
contains(TRACK_LUNAR))
790 setTrackMode(TrackMap.
value(TRACK_LUNAR));
793 else if (currentObject->
name() ==
i18n(
"Sun"))
795 if (currentTrackMode != TRACK_SOLAR && TrackMap.
contains(TRACK_SOLAR))
796 setTrackMode(TrackMap.
value(TRACK_SOLAR));
801 else if (currentTrackMode == TRACK_SOLAR || currentTrackMode == TRACK_LUNAR)
802 setTrackMode(TRACK_SIDEREAL);
808 if (currentObject->
name() ==
i18n(
"Sun") && currentTrackMode != TRACK_SOLAR)
821 KSMessageBox::Instance()->questionYesNo(
822 i18n(
"Warning! Looking at the Sun without proper protection can lead to irreversible eye damage!"),
823 i18n(
"Sun Warning"));
836 double targetAlt = ScopeTarget->altRefracted().Degrees();
838 if ((-90 <= minAlt && maxAlt <= 90) && (targetAlt < minAlt || targetAlt > maxAlt) && !altLimitsTrackingOnly)
841 i18n(
"Requested altitude %1 is outside the specified altitude limit boundary (%2,%3).",
843 QString::number(maxAlt,
'g', 3)), KSNotification::Mount, KSNotification::Warn);
844 qCInfo(KSTARS_INDI) <<
"Requested altitude " <<
QString::number(targetAlt,
'g', 3)
845 <<
" is outside the specified altitude limit boundary ("
851 if (Options::confirmBelowHorizon() && targetAlt < 0 && minAlt == -1)
855 if (minAlt < -90 && +90 < maxAlt)
856 Options::setConfirmBelowHorizon(
false);
858 checkObjectAndSend();
865 RAEle->value = currentRA;
866 DecEle->value = currentDEC;
870 AzEle->value = currentAz;
871 AltEle->value = currentAlt;
875 KSMessageBox::Instance()->questionYesNo(
i18n(
"Requested altitude is below the horizon. Are you sure you want to proceed?"),
876 i18n(
"Telescope Motion"), 15,
false);
879 checkObjectAndSend();
886 auto motionSP =
getSwitch(
"ON_COORD_SET");
888 if (motionSP ==
nullptr)
892 auto sp = motionSP->findOnSwitch();
894 (sp->name == std::string(
"TRACK") ||
895 sp->name == std::string(
"SLEW") ||
896 sp->name == std::string(
"FLIP")))
906bool Mount::Slew(
double ra,
double dec,
bool flip)
921 return Slew(&target, flip);
924bool Mount::Slew(
SkyPoint * ScopeTarget,
bool flip)
926 auto motionSP =
getSwitch(
"ON_COORD_SET");
931 auto slewSW = flip ? motionSP->findWidgetByName(
"FLIP") : motionSP->findWidgetByName(
"TRACK");
933 if (flip && (!slewSW))
934 slewSW = motionSP->findWidgetByName(
"TRACK");
937 slewSW = motionSP->findWidgetByName(
"SLEW");
942 if (slewSW->getState() != ISS_ON)
945 slewSW->setState(ISS_ON);
948 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: " << slewSW->getName();
954bool Mount::Sync(
double ra,
double dec)
961 return Sync(&target);
964bool Mount::Sync(
SkyPoint * ScopeTarget)
966 auto motionSP =
getSwitch(
"ON_COORD_SET");
971 auto syncSW = motionSP->findWidgetByName(
"SYNC");
976 if (syncSW->getState() != ISS_ON)
979 syncSW->setState(ISS_ON);
982 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Syncing...";
990 auto motionSP =
getSwitch(
"TELESCOPE_ABORT_MOTION");
995 auto abortSW = motionSP->findWidgetByName(
"ABORT");
1000 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Aborted." <<
Qt::endl;
1002 abortSW->setState(ISS_ON);
1005 inCustomParking =
false;
1012 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1017 auto parkSW = parkSP->findWidgetByName(
"PARK");
1022 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Parking..." <<
Qt::endl;
1025 parkSW->setState(ISS_ON);
1033 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1038 auto parkSW = parkSP->findWidgetByName(
"UNPARK");
1043 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: UnParking..." <<
Qt::endl;
1046 parkSW->setState(ISS_ON);
1052bool Mount::getEqCoords(
double * ra,
double * dec)
1054 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
1057 EqProp = getNumber(
"EQUATORIAL_COORD");
1062 auto RAEle = EqProp->findWidgetByName(
"RA");
1066 auto DecEle = EqProp->findWidgetByName(
"DEC");
1070 *ra = RAEle->getValue();
1071 *
dec = DecEle->getValue();
1076bool Mount::MoveNS(VerticalMotion dir, MotionCommand cmd)
1078 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1083 auto motionNorth = motionSP->findWidgetByName(
"MOTION_NORTH");
1084 auto motionSouth = motionSP->findWidgetByName(
"MOTION_SOUTH");
1086 if (!motionNorth || !motionSouth)
1090 if (dir == MOTION_NORTH && motionNorth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1093 if (dir == MOTION_SOUTH && motionSouth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1098 if (cmd == MOTION_START)
1100 if (dir == MOTION_NORTH)
1101 motionNorth->setState(ISS_ON);
1103 motionSouth->setState(ISS_ON);
1113 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1127 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1139bool Mount::MoveWE(HorizontalMotion dir, MotionCommand cmd)
1141 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1146 auto motionWest = motionSP->findWidgetByName(
"MOTION_WEST");
1147 auto motionEast = motionSP->findWidgetByName(
"MOTION_EAST");
1149 if (!motionWest || !motionEast)
1153 if (dir == MOTION_WEST && motionWest->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1156 if (dir == MOTION_EAST && motionEast->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1161 if (cmd == MOTION_START)
1163 if (dir == MOTION_WEST)
1164 motionWest->setState(ISS_ON);
1166 motionEast->setState(ISS_ON);
1174bool Mount::setSlewRate(
int index)
1176 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1181 if (index < 0 || index > slewRateSP->count())
1183 else if (slewRateSP->findOnSwitchIndex() == index)
1186 slewRateSP->reset();
1188 slewRateSP->at(index)->setState(ISS_ON);
1192 emit slewRateChanged(index);
1197int Mount::getSlewRate()
const
1199 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1204 return slewRateSP->findOnSwitchIndex();
1207void Mount::setAltLimits(
double minAltitude,
double maxAltitude,
bool trackingOnly)
1209 minAlt = minAltitude;
1210 maxAlt = maxAltitude;
1211 altLimitsTrackingOnly = trackingOnly;
1214bool Mount::setAlignmentModelEnabled(
bool enable)
1216 bool wasExecuted =
false;
1219 auto alignSwitch =
getSwitch(
"ALIGNMENT_SUBSYSTEM_ACTIVE");
1222 alignSwitch->at(0)->setState(enable ? ISS_ON : ISS_OFF);
1231 alignSwitch->reset();
1234 alignSwitch->at(2)->setState(ISS_ON);
1237 alignSwitch->at(0)->setState(ISS_ON);
1248 auto tleTextVec =
getText(
"SAT_TLE_TEXT");
1251 qCDebug(KSTARS_INDI) <<
"Property SAT_TLE_TEXT not found";
1255 auto tleText = tleTextVec->findWidgetByName(
"TLE");
1262 m_TLEIsSetForTracking =
true;
1263 g_satPassStart = satPassStart;
1264 g_satPassEnd = satPassEnd;
1270bool Mount::clearParking()
1272 auto parkSwitch =
getSwitch(
"TELESCOPE_PARK_OPTION");
1276 auto clearParkSW = parkSwitch->findWidgetByName(
"PARK_PURGE_DATA");
1280 parkSwitch->reset();
1281 clearParkSW->setState(ISS_ON);
1287bool Mount::clearAlignmentModel()
1289 bool wasExecuted =
false;
1292 auto clearSwitch =
getSwitch(
"ALIGNMENT_POINTSET_ACTION");
1293 auto commitSwitch =
getSwitch(
"ALIGNMENT_POINTSET_COMMIT");
1294 if (clearSwitch && commitSwitch)
1296 clearSwitch->reset();
1298 clearSwitch->at(4)->setState(ISS_ON);
1300 commitSwitch->at(0)->setState(ISS_ON);
1310 clearSwitch->reset();
1311 clearSwitch->at(1)->setState(ISS_ON);
1319Mount::Status Mount::status()
1321 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
1322 if (EqProp ==
nullptr)
1324 EqProp = getNumber(
"EQUATORIAL_COORD");
1325 if (EqProp ==
nullptr)
1329 return status(EqProp);
1332const QString Mount::statusString(Mount::Status status,
bool translated)
const
1336 case ISD::Mount::MOUNT_MOVING:
1337 return (translated ? mountStates[status].
toString() : mountStates[status].untranslatedText() +
QString(
" %1").arg(
1338 getManualMotionString()));
1340 return translated ? mountStates[
status].toString() : mountStates[
status].untranslatedText();
1344QString Mount::getManualMotionString()
const
1348 auto movementSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1351 if (movementSP->at(MOTION_NORTH)->getState() == ISS_ON)
1353 else if (movementSP->at(MOTION_SOUTH)->getState() == ISS_ON)
1357 movementSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1360 if (movementSP->at(MOTION_WEST)->getState() == ISS_ON)
1362 else if (movementSP->at(MOTION_EAST)->getState() == ISS_ON)
1366 return QString(
"%1%2").
arg(NSMotion, WEMotion);
1369bool Mount::setTrackEnabled(
bool enable)
1371 auto trackSP =
getSwitch(
"TELESCOPE_TRACK_STATE");
1375 auto trackON = trackSP->findWidgetByName(
"TRACK_ON");
1376 auto trackOFF = trackSP->findWidgetByName(
"TRACK_OFF");
1378 if (!trackON || !trackOFF)
1381 trackON->setState(enable ? ISS_ON : ISS_OFF);
1382 trackOFF->setState(enable ? ISS_OFF : ISS_ON);
1389bool Mount::isTracking()
1391 return (
status() == MOUNT_TRACKING);
1394bool Mount::setTrackMode(uint8_t index)
1396 auto trackModeSP =
getSwitch(
"TELESCOPE_TRACK_MODE");
1400 if (index >= trackModeSP->nsp)
1403 trackModeSP->reset();
1404 trackModeSP->at(index)->setState(ISS_ON);
1411bool Mount::getTrackMode(uint8_t &index)
1413 auto trackModeSP =
getSwitch(
"TELESCOPE_TRACK_MODE");
1417 index = trackModeSP->findOnSwitchIndex();
1422bool Mount::setCustomTrackRate(
double raRate,
double deRate)
1424 auto trackRateNP = getNumber(
"TELESCOPE_TRACK_RATE");
1428 auto raRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_RA");
1429 auto deRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_DE");
1431 if (!raRateN || !deRateN)
1434 raRateN->setValue(raRate);
1435 deRateN->setValue(deRate);
1442bool Mount::getCustomTrackRate(
double &raRate,
double &deRate)
1444 auto trackRateNP = getNumber(
"TELESCOPE_TRACK_RATE");
1448 auto raRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_RA");
1449 auto deRateN = trackRateNP->findWidgetByName(
"TRACK_RATE_DE");
1451 if (!raRateN || !deRateN)
1454 raRate = raRateN->getValue();
1455 deRate = deRateN->getValue();
1461bool Mount::sendParkingOptionCommand(ParkOptionCommand command)
1463 auto parkOptionsSP =
getSwitch(
"TELESCOPE_PARK_OPTION");
1467 parkOptionsSP->reset();
1468 parkOptionsSP->at(command)->setState(ISS_ON);
1474Mount::Status Mount::status(INumberVectorProperty * nvp)
1476 Status newMountStatus = MOUNT_ERROR;
1481 newMountStatus = MOUNT_MOVING;
1482 else if (isParked())
1483 newMountStatus = MOUNT_PARKED;
1485 newMountStatus = MOUNT_IDLE;
1490 newMountStatus = MOUNT_MOVING;
1491 else if (inCustomParking)
1493 inCustomParking =
false;
1495 sendParkingOptionCommand(PARK_OPTION_CURRENT);
1497 sendParkingOptionCommand(PARK_OPTION_WRITE_DATA);
1499 newMountStatus = MOUNT_TRACKING;
1502 newMountStatus = MOUNT_TRACKING;
1507 newMountStatus = MOUNT_MOVING;
1510 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1511 if (parkSP && parkSP->getState() == IPS_BUSY)
1512 newMountStatus = MOUNT_PARKING;
1514 newMountStatus = MOUNT_SLEWING;
1519 inCustomParking =
false;
1520 newMountStatus = MOUNT_ERROR;
1523 if (previousMountStatus != newMountStatus)
1526 previousMountStatus = newMountStatus;
1527 return newMountStatus;
1532 dms lst = KStarsData::Instance()->
geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
1533 return dms(lst.Degrees() - currentCoords.ra().Degrees());
1536bool Mount::isReversed(INDI_EQ_AXIS axis)
1538 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1542 return reversed->at(axis == AXIS_DE ? 0 : 1)->getState() == ISS_ON;
1545bool Mount::setReversedEnabled(INDI_EQ_AXIS axis,
bool enabled)
1547 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1551 reversed->at(axis == AXIS_DE ? 0 : 1)->setState(enabled ? ISS_ON : ISS_OFF);
1558 updateCoordinatesTimer.
stop();
1559 centerLockTimer.
stop();
1567 argument << static_cast<int>(source);
1578 dest =
static_cast<ISD::Mount::Status
>(a);
1585 argument << static_cast<int>(source);
1596 dest =
static_cast<ISD::Mount::PierSide
>(a);
void sendNewProperty(INDI::Property prop)
Send new property command to server.
INDI::PropertyView< IText > * getText(const QString &name) const
INDI::PropertyView< ISwitch > * getSwitch(const QString &name) const
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()
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.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
virtual QString name(void) const
The sky coordinates of a point in the sky.
void setDec(dms d)
Sets Dec, the current Declination.
void setRA(dms &r)
Sets RA, the current Right Ascension.
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.
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
GeoCoordinates geo(const QVariant &location)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
QDebug operator<<(QDebug dbg, const PerceptualColor::MultiSpinBoxSection &value)
QCA_EXPORT QVariant getProperty(const QString &name)
bool contains(const Key &key) 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 arg(Args &&... args) const const
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)
void setInterval(int msec)
bool isActive() const const
bool isValid() const const