9#include "ksmessagebox.h"
10#include "driverinfo.h"
14#include "skymapcomposite.h"
15#include "ksnotification.h"
17#include <KActionCollection>
20#include <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)
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();
240 auto currentStatus = status(nvp);
242 if (nvp->getState() == IPS_BUSY && EqCoordPreviousState != IPS_BUSY)
244 if (currentStatus == MOUNT_SLEWING)
245 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);
266 EqCoordPreviousState = nvp->getState();
274 else if (nvp->isNameMatch(
"HORIZONTAL_COORD") && m_hasEquatorialCoordProperty ==
false)
276 auto Az = nvp->findWidgetByName(
"AZ");
277 auto Alt = nvp->findWidgetByName(
"ALT");
279 if (Az ==
nullptr || Alt ==
nullptr)
282 currentCoords.
setAz(Az->value);
283 currentCoords.
setAlt(Alt->value);
291 if (! updateCoordinatesTimer.
isActive())
292 updateCoordinatesTimer.
start();
296 else if (nvp->isNameMatch(
"POLLING_PERIOD"))
299 auto period = nvp->findWidgetByName(
"PERIOD_MS");
300 if (period !=
nullptr)
301 updateCoordinatesTimer.
setInterval(
static_cast<int>(period->getValue()));
306void Mount::processSwitch(INDI::Property prop)
308 bool manualMotionChanged =
false;
309 auto svp = prop.getSwitch();
311 if (svp->isNameMatch(
"CONNECTION"))
313 auto conSP = svp->findWidgetByName(
"CONNECT");
319 if (conSP->getState() == ISS_ON)
324 centerLockTimer.
stop();
328 else if (svp->isNameMatch(
"TELESCOPE_PARK"))
330 else if (svp->isNameMatch(
"TELESCOPE_ABORT_MOTION"))
332 if (svp->s == IPS_OK)
334 inCustomParking =
false;
335 KSNotification::event(
QLatin1String(
"MountAborted"),
i18n(
"Mount motion was aborted"), KSNotification::Mount,
336 KSNotification::Warn);
339 else if (svp->isNameMatch(
"TELESCOPE_PIER_SIDE"))
341 int currentSide = IUFindOnSwitchIndex(svp);
342 if (currentSide != m_PierSide)
344 m_PierSide =
static_cast<PierSide
>(currentSide);
345 emit pierSideChanged(m_PierSide);
348 else if (svp->isNameMatch(
"TELESCOPE_TRACK_MODE"))
350 auto sp = svp->findOnSwitch();
353 if (sp->isNameMatch(
"TRACK_SIDEREAL"))
354 currentTrackMode = TRACK_SIDEREAL;
355 else if (sp->isNameMatch(
"TRACK_SOLAR"))
356 currentTrackMode = TRACK_SOLAR;
357 else if (sp->isNameMatch(
"TRACK_LUNAR"))
358 currentTrackMode = TRACK_LUNAR;
360 currentTrackMode = TRACK_CUSTOM;
363 else if (svp->isNameMatch(
"TELESCOPE_MOTION_NS"))
364 manualMotionChanged =
true;
365 else if (svp->isNameMatch(
"TELESCOPE_MOTION_WE"))
366 manualMotionChanged =
true;
367 else if (svp->isNameMatch(
"TELESCOPE_REVERSE_MOTION"))
369 emit axisReversed(AXIS_DE, svp->at(0)->getState() == ISS_ON);
370 emit axisReversed(AXIS_RA, svp->at(1)->getState() == ISS_ON);
373 if (manualMotionChanged)
375 auto NSCurrentMotion =
getSwitch(
"TELESCOPE_MOTION_NS")->getState();
376 auto WECurrentMotion =
getSwitch(
"TELESCOPE_MOTION_WE")->getState();
377 inCustomParking =
false;
378 inManualMotion = (NSCurrentMotion == IPS_BUSY || WECurrentMotion == IPS_BUSY);
382void Mount::processText(INDI::Property prop)
384 auto tvp = prop.getText();
385 if (tvp->isNameMatch(
"SAT_TLE_TEXT"))
387 if ((tvp->getState() == IPS_OK) && (m_TLEIsSetForTracking))
389 auto trajWindow =
getText(
"SAT_PASS_WINDOW");
392 qCDebug(KSTARS_INDI) <<
"Property SAT_PASS_WINDOW not found";
396 auto trajStart = trajWindow->findWidgetByName(
"SAT_PASS_WINDOW_START");
397 auto trajEnd = trajWindow->findWidgetByName(
"SAT_PASS_WINDOW_END");
399 if (!trajStart || !trajEnd)
401 qCDebug(KSTARS_INDI) <<
"Start or end in SAT_PASS_WINDOW not found";
409 m_windowIsSetForTracking =
true;
414 else if (tvp->isNameMatch(
"SAT_PASS_WINDOW"))
416 if ((tvp->getState() == IPS_OK) && (m_TLEIsSetForTracking) && (m_windowIsSetForTracking))
418 auto trackSwitchV =
getSwitch(
"SAT_TRACKING_STAT");
421 qCDebug(KSTARS_INDI) <<
"Property SAT_TRACKING_STAT not found";
425 auto trackSwitch = trackSwitchV->findWidgetByName(
"SAT_TRACK");
428 trackSwitchV->reset();
429 trackSwitch->setState(ISS_ON);
432 m_TLEIsSetForTracking =
false;
433 m_windowIsSetForTracking =
false;
446 auto sp = svp->findWidgetByName(
"PARK");
449 if (svp->getState() == IPS_ALERT)
452 emit newParkStatus(PARK_ERROR);
455 m_ParkStatus = (sp->getState() == ISS_ON) ? PARK_PARKED : PARK_UNPARKED;
456 KSNotification::event(
QLatin1String(
"MountParkingFailed"),
i18n(
"Mount parking failed"), KSNotification::Mount,
457 KSNotification::Alert);
459 else if (svp->getState() == IPS_BUSY && sp->s == ISS_ON && m_ParkStatus != PARK_PARKING)
461 m_ParkStatus = PARK_PARKING;
462 KSNotification::event(
QLatin1String(
"MountParking"),
i18n(
"Mount parking is in progress"), KSNotification::Mount);
463 currentObject =
nullptr;
465 emit newParkStatus(m_ParkStatus);
467 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_OFF && m_ParkStatus != PARK_UNPARKING)
469 m_ParkStatus = PARK_UNPARKING;
470 KSNotification::event(
QLatin1String(
"MountUnParking"),
i18n(
"Mount unparking is in progress"), KSNotification::Mount);
472 emit newParkStatus(m_ParkStatus);
474 else if (svp->getState() == IPS_OK && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKED)
476 m_ParkStatus = PARK_PARKED;
477 KSNotification::event(
QLatin1String(
"MountParked"),
i18n(
"Mount parked"), KSNotification::Mount);
478 currentObject =
nullptr;
480 emit newParkStatus(m_ParkStatus);
492 else if ( (svp->getState() == IPS_OK || svp->getState() == IPS_IDLE) && sp->getState() == ISS_OFF
493 && m_ParkStatus != PARK_UNPARKED)
495 m_ParkStatus = PARK_UNPARKED;
496 KSNotification::event(
QLatin1String(
"MountUnparked"),
i18n(
"Mount unparked"), KSNotification::Mount);
497 currentObject =
nullptr;
499 emit newParkStatus(m_ParkStatus);
510bool Mount::canGuide()
512 auto raPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_WE");
513 auto decPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_NS");
515 return raPulse && decPulse;
520 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
525 auto parkSW = parkSP->findWidgetByName(
"PARK");
527 return (parkSW !=
nullptr);
530bool Mount::isSlewing()
532 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
537 return (EqProp->getState() == IPS_BUSY);
540bool Mount::isInMotion()
542 return (isSlewing() || inManualMotion);
545bool Mount::doPulse(GuideDirection ra_dir,
int ra_msecs, GuideDirection dec_dir,
int dec_msecs)
547 if (canGuide() ==
false)
550 bool raOK = doPulse(ra_dir, ra_msecs);
551 bool decOK = doPulse(dec_dir, dec_msecs);
553 return raOK && decOK;
556bool Mount::doPulse(GuideDirection dir,
int msecs)
558 auto raPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_WE");
559 auto decPulse = getNumber(
"TELESCOPE_TIMED_GUIDE_NS");
560 INDI::PropertyView<INumber> *npulse =
nullptr;
561 INDI::WidgetView<INumber> *dirPulse =
nullptr;
563 if (!raPulse || !decPulse)
570 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_W");
575 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_E");
580 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_N");
585 dirPulse = npulse->findWidgetByName(
"TIMED_GUIDE_S");
595 dirPulse->setValue(msecs);
603void Mount::setCustomParking(
SkyPoint * coords)
606 if (coords ==
nullptr)
611 inCustomParking = rc;
617 double maxrad = 1000.0 / Options::zoomFactor();
622void Mount::centerLock()
624 if (Options::isTracking() ==
false ||
631 Options::setIsTracking(
true);
633 centerLockTimer.
start();
636void Mount::centerUnlock()
639 centerLockTimer.
stop();
644 INumber *RAEle =
nullptr;
645 INumber *DecEle =
nullptr;
646 INumber *AzEle =
nullptr;
647 INumber *AltEle =
nullptr;
648 double currentRA = 0, currentDEC = 0, currentAlt = 0, currentAz = 0;
649 bool useJ2000(
false);
651 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
655 EqProp = getNumber(
"EQUATORIAL_COORD");
660 auto HorProp = getNumber(
"HORIZONTAL_COORD");
662 if (EqProp && EqProp->getPermission() == IP_RO)
665 if (HorProp && HorProp->getPermission() == IP_RO)
672 RAEle = EqProp->findWidgetByName(
"RA");
676 DecEle = EqProp->findWidgetByName(
"DEC");
683 currentRA = RAEle->value;
684 currentDEC = DecEle->value;
691 AzEle = IUFindNumber(HorProp,
"AZ");
694 AltEle = IUFindNumber(HorProp,
"ALT");
698 currentAz = AzEle->value;
699 currentAlt = AltEle->value;
703 if (EqProp ==
nullptr && HorProp ==
nullptr)
708 auto sendToMountDevice = [ = ]()
731 ScopeTarget->
setRA0(ScopeTarget->
ra());
734 ra = ScopeTarget->
ra();
735 de = ScopeTarget->
dec();
739 ra = ScopeTarget->
ra0();
740 de = ScopeTarget->
dec0();
745 ra = ScopeTarget->
ra();
746 de = ScopeTarget->
dec();
749 RAEle->value = ra.
Hours();
753 qCDebug(KSTARS_INDI) <<
"ISD:Telescope sending coords RA:" << ra.
toHMSString() <<
754 "(" << RAEle->value <<
") DE:" << de.
toDMSString() <<
755 "(" << DecEle->value <<
")";
757 RAEle->value = currentRA;
758 DecEle->value = currentDEC;
763 AzEle->value = ScopeTarget->
az().
Degrees();
766 AzEle->value = currentAz;
767 AltEle->value = currentAlt;
776 auto checkObjectAndSend = [ = ]()
783 auto checkTrackModes = [ = ]()
788 if (currentObject->
type() == SkyObject::MOON)
790 if (currentTrackMode != TRACK_LUNAR && TrackMap.
contains(TRACK_LUNAR))
791 setTrackMode(TrackMap.
value(TRACK_LUNAR));
794 else if (currentObject->
name() ==
i18n(
"Sun"))
796 if (currentTrackMode != TRACK_SOLAR && TrackMap.
contains(TRACK_SOLAR))
797 setTrackMode(TrackMap.
value(TRACK_SOLAR));
802 else if (currentTrackMode == TRACK_SOLAR || currentTrackMode == TRACK_LUNAR)
803 setTrackMode(TRACK_SIDEREAL);
809 if (currentObject->
name() ==
i18n(
"Sun") && currentTrackMode != TRACK_SOLAR)
822 KSMessageBox::Instance()->questionYesNo(
823 i18n(
"Warning! Looking at the Sun without proper protection can lead to irreversible eye damage!"),
824 i18n(
"Sun Warning"));
839 if ((-90 <= minAlt && maxAlt <= 90) && (targetAlt < minAlt || targetAlt > maxAlt))
842 i18n(
"Requested altitude %1 is outside the specified altitude limit boundary (%2,%3).",
844 QString::number(maxAlt,
'g', 3)), KSNotification::Mount, KSNotification::Warn);
845 qCInfo(KSTARS_INDI) <<
"Requested altitude " <<
QString::number(targetAlt,
'g', 3)
846 <<
" is outside the specified altitude limit boundary ("
852 if (Options::confirmBelowHorizon() && targetAlt < 0 && minAlt == -1)
856 if (minAlt < -90 && +90 < maxAlt)
857 Options::setConfirmBelowHorizon(
false);
859 checkObjectAndSend();
866 RAEle->value = currentRA;
867 DecEle->value = currentDEC;
871 AzEle->value = currentAz;
872 AltEle->value = currentAlt;
876 KSMessageBox::Instance()->questionYesNo(
i18n(
"Requested altitude is below the horizon. Are you sure you want to proceed?"),
877 i18n(
"Telescope Motion"), 15,
false);
880 checkObjectAndSend();
887 auto motionSP =
getSwitch(
"ON_COORD_SET");
889 if (motionSP ==
nullptr)
893 auto sp = motionSP->findOnSwitch();
895 (sp->name == std::string(
"TRACK") ||
896 sp->name == std::string(
"SLEW") ||
897 sp->name == std::string(
"FLIP")))
907bool Mount::Slew(
double ra,
double dec,
bool flip)
922 return Slew(&target, flip);
925bool Mount::Slew(
SkyPoint * ScopeTarget,
bool flip)
927 auto motionSP =
getSwitch(
"ON_COORD_SET");
932 auto slewSW = flip ? motionSP->findWidgetByName(
"FLIP") : motionSP->findWidgetByName(
"TRACK");
934 if (flip && (!slewSW))
935 slewSW = motionSP->findWidgetByName(
"TRACK");
938 slewSW = motionSP->findWidgetByName(
"SLEW");
943 if (slewSW->getState() != ISS_ON)
946 slewSW->setState(ISS_ON);
949 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: " << slewSW->getName();
955bool Mount::Sync(
double ra,
double dec)
962 return Sync(&target);
965bool Mount::Sync(
SkyPoint * ScopeTarget)
967 auto motionSP =
getSwitch(
"ON_COORD_SET");
972 auto syncSW = motionSP->findWidgetByName(
"SYNC");
977 if (syncSW->getState() != ISS_ON)
980 syncSW->setState(ISS_ON);
983 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Syncing...";
991 auto motionSP =
getSwitch(
"TELESCOPE_ABORT_MOTION");
996 auto abortSW = motionSP->findWidgetByName(
"ABORT");
1001 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Aborted." <<
Qt::endl;
1003 abortSW->setState(ISS_ON);
1006 inCustomParking =
false;
1013 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1018 auto parkSW = parkSP->findWidgetByName(
"PARK");
1023 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: Parking..." <<
Qt::endl;
1026 parkSW->setState(ISS_ON);
1034 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1039 auto parkSW = parkSP->findWidgetByName(
"UNPARK");
1044 qCDebug(KSTARS_INDI) <<
"ISD:Telescope: UnParking..." <<
Qt::endl;
1047 parkSW->setState(ISS_ON);
1053bool Mount::getEqCoords(
double * ra,
double * dec)
1055 auto EqProp = getNumber(
"EQUATORIAL_EOD_COORD");
1058 EqProp = getNumber(
"EQUATORIAL_COORD");
1063 auto RAEle = EqProp->findWidgetByName(
"RA");
1067 auto DecEle = EqProp->findWidgetByName(
"DEC");
1071 *ra = RAEle->getValue();
1072 *
dec = DecEle->getValue();
1077bool Mount::MoveNS(VerticalMotion dir, MotionCommand cmd)
1079 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1084 auto motionNorth = motionSP->findWidgetByName(
"MOTION_NORTH");
1085 auto motionSouth = motionSP->findWidgetByName(
"MOTION_SOUTH");
1087 if (!motionNorth || !motionSouth)
1091 if (dir == MOTION_NORTH && motionNorth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1094 if (dir == MOTION_SOUTH && motionSouth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1099 if (cmd == MOTION_START)
1101 if (dir == MOTION_NORTH)
1102 motionNorth->setState(ISS_ON);
1104 motionSouth->setState(ISS_ON);
1114 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1128 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_NS");
1140bool Mount::MoveWE(HorizontalMotion dir, MotionCommand cmd)
1142 auto motionSP =
getSwitch(
"TELESCOPE_MOTION_WE");
1147 auto motionWest = motionSP->findWidgetByName(
"MOTION_WEST");
1148 auto motionEast = motionSP->findWidgetByName(
"MOTION_EAST");
1150 if (!motionWest || !motionEast)
1154 if (dir == MOTION_WEST && motionWest->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1157 if (dir == MOTION_EAST && motionEast->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
1162 if (cmd == MOTION_START)
1164 if (dir == MOTION_WEST)
1165 motionWest->setState(ISS_ON);
1167 motionEast->setState(ISS_ON);
1175bool Mount::setSlewRate(
int index)
1177 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1182 if (index < 0 || index > slewRateSP->count())
1184 else if (slewRateSP->findOnSwitchIndex() == index)
1187 slewRateSP->reset();
1189 slewRateSP->at(index)->setState(ISS_ON);
1193 emit slewRateChanged(index);
1198int Mount::getSlewRate()
const
1200 auto slewRateSP =
getSwitch(
"TELESCOPE_SLEW_RATE");
1205 return slewRateSP->findOnSwitchIndex();
1208void Mount::setAltLimits(
double minAltitude,
double maxAltitude)
1210 minAlt = minAltitude;
1211 maxAlt = maxAltitude;
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)
1480 return MOUNT_MOVING;
1481 else if (isParked())
1482 return MOUNT_PARKED;
1488 return MOUNT_MOVING;
1489 else if (inCustomParking)
1491 inCustomParking =
false;
1493 sendParkingOptionCommand(PARK_OPTION_CURRENT);
1495 sendParkingOptionCommand(PARK_OPTION_WRITE_DATA);
1497 return MOUNT_TRACKING;
1500 return MOUNT_TRACKING;
1505 return MOUNT_MOVING;
1507 auto parkSP =
getSwitch(
"TELESCOPE_PARK");
1508 if (parkSP && parkSP->getState() == IPS_BUSY)
1509 return MOUNT_PARKING;
1511 return MOUNT_SLEWING;
1515 inCustomParking =
false;
1524 dms lst = KStarsData::Instance()->
geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
1528bool Mount::isReversed(INDI_EQ_AXIS axis)
1530 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1534 return reversed->at(axis == AXIS_DE ? 0 : 1)->getState() == ISS_ON;
1537bool Mount::setReversedEnabled(INDI_EQ_AXIS axis,
bool enabled)
1539 auto reversed =
getSwitch(
"TELESCOPE_REVERSE_MOTION");
1543 reversed->at(axis == AXIS_DE ? 0 : 1)->setState(enabled ? ISS_ON : ISS_OFF);
1550 updateCoordinatesTimer.
stop();
1551 centerLockTimer.
stop();
1559 argument << static_cast<int>(source);
1570 dest =
static_cast<ISD::Mount::Status
>(a);
1577 argument << static_cast<int>(source);
1588 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()
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.
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 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
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
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.
void setAlt(dms alt)
Sets Alt, the Altitude.
void HorizontalToEquatorial(const dms *LST, const dms *lat)
Determine the (RA, Dec) coordinates of the SkyPoint from its (Altitude, Azimuth) coordinates,...
void setAz(dms az)
Sets Az, the Azimuth.
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.
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
GeoCoordinates geo(const QVariant &location)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
QCA_EXPORT QVariant getProperty(const QString &name)
QString toString(QStringView format, QCalendar cal) const const
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