Kstars

inditelescopelite.cpp
1 /*
2  SPDX-FileCopyrightText: 2012 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include <indi/indidevice.h>
8 
9 #include "Options.h"
10 
11 #include "clientmanagerlite.h"
12 #include "inditelescopelite.h"
13 
14 #include "kstarslite.h"
15 #include "skymaplite.h"
16 
17 TelescopeLite::TelescopeLite(INDI::BaseDevice *device)
18  : minAlt(-1), maxAlt(-1), IsParked(false), clientManager(KStarsLite::Instance()->clientManagerLite()),
19  baseDevice(device), slewRateIndex(0)
20 {
21  setDeviceName(device->getDeviceName());
22  //Whenever slew rate is changed (or once it was initialized) we update it
23  connect(clientManager, &ClientManagerLite::newINDIProperty, this, &TelescopeLite::updateSlewRate);
24  connect(clientManager, &ClientManagerLite::newINDISwitch, this, &TelescopeLite::updateSlewRate);
25 }
26 
27 void TelescopeLite::updateSlewRate(const QString &deviceName, const QString &propName)
28 {
29  if (deviceName == baseDevice->getDeviceName() && propName == "TELESCOPE_SLEW_RATE")
30  {
31  auto slewRateSP = baseDevice->getSwitch("TELESCOPE_SLEW_RATE");
32  int index = 0;
33  for (int i = 0; i < slewRateSP->count(); ++i)
34  {
35  if (slewRateSP->at(i).getState() == ISS_ON)
36  {
37  index = i;
38  break;
39  }
40  }
41  m_slewRateLabels.clear();
42  for (int i = 0; i < slewRateSP->count(); ++i)
43  {
44  m_slewRateLabels.push_back(slewRateSP->at(i)->getLabel());
45  }
46  emit slewRateUpdate(index, m_slewRateLabels.size());
47  setSlewRate(index);
48  }
49 }
50 
51 TelescopeLite::~TelescopeLite()
52 {
53 }
54 
55 void TelescopeLite::setSlewDecreasable(bool slewDecreasable)
56 {
57  if (m_slewDecreasable != slewDecreasable)
58  {
59  m_slewDecreasable = slewDecreasable;
60  emit slewDecreasableChanged(slewDecreasable);
61  }
62 }
63 
64 void TelescopeLite::setSlewIncreasable(bool slewIncreasable)
65 {
66  if (m_slewIncreasable != slewIncreasable)
67  {
68  m_slewIncreasable = slewIncreasable;
69  emit slewIncreasableChanged(slewIncreasable);
70  }
71 }
72 
73 void TelescopeLite::setSlewRateLabel(const QString &slewRateLabel)
74 {
75  if (m_slewRateLabel != slewRateLabel)
76  {
77  m_slewRateLabel = slewRateLabel;
78  emit slewRateLabelChanged(slewRateLabel);
79  }
80 }
81 
82 void TelescopeLite::setDeviceName(const QString &deviceName)
83 {
84  if (m_deviceName != deviceName)
85  {
86  m_deviceName = deviceName;
87  emit deviceNameChanged(deviceName);
88  }
89 }
90 
91 void TelescopeLite::registerProperty(INDI::Property prop)
92 {
93  if (prop->isNameMatch("TELESCOPE_INFO"))
94  {
95  auto ti = prop->getNumber();
96 
97  if (!ti)
98  return;
99 
100  // bool aperture_ok=false, focal_ok=false;
101  // double temp=0;
102  }
103 
104  if (prop->isNameMatch("TELESCOPE_PARK"))
105  {
106  auto svp = prop->getSwitch();
107 
108  if (svp)
109  {
110  auto sp = svp->findWidgetByName("PARK");
111  if (sp)
112  {
113  IsParked = ((sp->getState() == ISS_ON) && svp->getState() == IPS_OK);
114  }
115  }
116  }
117 }
118 
119 void TelescopeLite::processNumber(INumberVectorProperty *nvp)
120 {
121  if (!strcmp(nvp->name, "EQUATORIAL_EOD_COORD"))
122  {
123  INumber *RA = IUFindNumber(nvp, "RA");
124  INumber *DEC = IUFindNumber(nvp, "DEC");
125 
126  if (RA == nullptr || DEC == nullptr)
127  return;
128 
129  currentCoord.setRA(RA->value);
130  currentCoord.setDec(DEC->value);
131 
132  //KStarsLite::Instance()->map()->update();
133 
134  //emit numberUpdated(nvp);
135 
136  return;
137  }
138 
139  if (!strcmp(nvp->name, "EQUATORIAL_COORD"))
140  {
141  INumber *RA = IUFindNumber(nvp, "RA");
142  INumber *DEC = IUFindNumber(nvp, "DEC");
143 
144  if (RA == nullptr || DEC == nullptr)
145  return;
146 
147  currentCoord.setRA0(RA->value);
148  currentCoord.setDec0(DEC->value);
149  currentCoord.apparentCoord(static_cast<long double>(J2000), KStarsLite::Instance()->data()->ut().djd());
150 
151  //KStarsLite::Instance()->map()->update();
152 
153  //emit numberUpdated(nvp);
154 
155  return;
156  }
157 
158  if (!strcmp(nvp->name, "HORIZONTAL_COORD"))
159  {
160  INumber *Az = IUFindNumber(nvp, "AZ");
161  INumber *Alt = IUFindNumber(nvp, "ALT");
162 
163  if (Az == nullptr || Alt == nullptr)
164  return;
165 
166  currentCoord.setAz(Az->value);
167  currentCoord.setAlt(Alt->value);
168  currentCoord.HorizontalToEquatorial(KStarsLite::Instance()->data()->lst(),
169  KStarsLite::Instance()->data()->geo()->lat());
170 
171  //KStarsLite::Instance()->map()->update();
172 
173  //emit numberUpdated(nvp);
174 
175  return;
176  }
177 
178  //DeviceDecorator::processNumber(nvp);
179 }
180 
181 void TelescopeLite::processSwitch(ISwitchVectorProperty *svp)
182 {
183  Q_UNUSED(svp);
184  /*if (!strcmp(svp->name, "TELESCOPE_PARK"))
185  {
186  ISwitch *sp = IUFindSwitch(svp, "PARK");
187  if (sp)
188  {
189  IsParked = ( (sp->s == ISS_ON) && svp->s == IPS_OK);
190  }
191 
192  //emit switchUpdated(svp);
193 
194  return;
195 
196  }*/
197 }
198 
199 bool TelescopeLite::canGuide()
200 {
201  auto raPulse = baseDevice->getNumber("TELESCOPE_TIMED_GUIDE_WE");
202  auto decPulse = baseDevice->getNumber("TELESCOPE_TIMED_GUIDE_NS");
203 
204  return raPulse && decPulse;
205 }
206 
207 bool TelescopeLite::canSync()
208 {
209  auto motionSP = baseDevice->getSwitch("ON_COORD_SET");
210 
211  if (!motionSP)
212  return false;
213 
214  auto syncSW = motionSP->findWidgetByName("SYNC");
215 
216  return (syncSW != nullptr);
217 }
218 
219 bool TelescopeLite::canPark()
220 {
221  auto parkSP = baseDevice->getSwitch("TELESCOPE_PARK");
222 
223  if (!parkSP)
224  return false;
225 
226  auto parkSW = parkSP->findWidgetByName("PARK");
227 
228  return (parkSW != nullptr);
229 }
230 
231 bool TelescopeLite::isSlewing()
232 {
233  auto EqProp = baseDevice->getNumber("EQUATORIAL_EOD_COORD");
234  if (!EqProp)
235  return false;
236 
237  return (EqProp->getState() == IPS_BUSY);
238 }
239 
240 bool TelescopeLite::isInMotion()
241 {
242  bool inMotion = false;
243  bool inSlew = isSlewing();
244 
245  auto movementSP = baseDevice->getSwitch("TELESCOPE_MOTION_NS");
246  if (movementSP)
247  inMotion = (movementSP->getState() == IPS_BUSY);
248 
249  movementSP = baseDevice->getSwitch("TELESCOPE_MOTION_WE");
250  if (movementSP)
251  inMotion = ((movementSP->getState() == IPS_BUSY) || inMotion);
252 
253  return (inSlew || inMotion);
254 }
255 
256 bool TelescopeLite::sendCoords(SkyPoint *ScopeTarget)
257 {
258  INumber *RAEle = nullptr;
259  INumber *DecEle = nullptr;
260  INumber *AzEle = nullptr;
261  INumber *AltEle = nullptr;
262  double currentRA = 0, currentDEC = 0, currentAlt = 0, currentAz = 0, targetAlt = 0;
263  bool useJ2000(false);
264 
265  auto EqProp = baseDevice->getNumber("EQUATORIAL_EOD_COORD");
266  if (!EqProp)
267  {
268  // J2000 Property
269  EqProp = baseDevice->getNumber("EQUATORIAL_COORD");
270  if (EqProp)
271  useJ2000 = true;
272  }
273 
274  auto HorProp = baseDevice->getNumber("HORIZONTAL_COORD");
275 
276  if (EqProp && EqProp->getPermission() == IP_RO)
277  EqProp = nullptr;
278 
279  if (HorProp && HorProp->getPermission() == IP_RO)
280  HorProp = nullptr;
281 
282  //qDebug() << "Skymap click - RA: " << scope_target->ra().toHMSString() << " DEC: " << scope_target->dec().toDMSString();
283 
284  if (EqProp)
285  {
286  RAEle = IUFindNumber(EqProp, "RA");
287  if (!RAEle)
288  return false;
289  DecEle = IUFindNumber(EqProp, "DEC");
290  if (!DecEle)
291  return false;
292 
293  //if (useJ2000)
294  //ScopeTarget->apparentCoord( KStars::Instance()->data()->ut().djd(), static_cast<long double>(J2000));
295 
296  currentRA = RAEle->value;
297  currentDEC = DecEle->value;
298 
299  ScopeTarget->EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
300  }
301 
302  if (HorProp)
303  {
304  AzEle = IUFindNumber(HorProp, "AZ");
305  if (!AzEle)
306  return false;
307  AltEle = IUFindNumber(HorProp, "ALT");
308  if (!AltEle)
309  return false;
310 
311  currentAz = AzEle->value;
312  currentAlt = AltEle->value;
313  }
314 
315  /* Could not find either properties! */
316  if (EqProp == nullptr && HorProp == nullptr)
317  return false;
318 
319  //targetAz = ScopeTarget->az().Degrees();
320  targetAlt = ScopeTarget->altRefracted().Degrees();
321  if (targetAlt < 0)
322  {
323  return false;
324  }
325 
326  if (EqProp)
327  {
328  dms ra, de;
329 
330  if (useJ2000)
331  {
332  // If we have invalid DEC, then convert coords to J2000
333  if (ScopeTarget->dec0().Degrees() == 180.0)
334  {
335  ScopeTarget->setRA0(ScopeTarget->ra());
336  ScopeTarget->setDec0(ScopeTarget->dec());
337  ScopeTarget->apparentCoord( KStarsLite::Instance()->data()->ut().djd(), static_cast<long double>(J2000));
338  ra = ScopeTarget->ra();
339  de = ScopeTarget->dec();
340  }
341  else
342  {
343  ra = ScopeTarget->ra0();
344  de = ScopeTarget->dec0();
345  }
346  }
347  else
348  {
349  ra = ScopeTarget->ra();
350  de = ScopeTarget->dec();
351  }
352 
353  RAEle->value = ra.Hours();
354  DecEle->value = de.Degrees();
355  clientManager->sendNewNumber(EqProp);
356 
357  RAEle->value = currentRA;
358  DecEle->value = currentDEC;
359  }
360  // Only send Horizontal Coord property if Equatorial is not available.
361  else if (HorProp)
362  {
363  AzEle->value = ScopeTarget->az().Degrees();
364  AltEle->value = ScopeTarget->alt().Degrees();
365  clientManager->sendNewNumber(HorProp);
366  AzEle->value = currentAz;
367  AltEle->value = currentAlt;
368  }
369 
370  return true;
371 }
372 
373 bool TelescopeLite::slew(double ra, double dec)
374 {
375  SkyPoint target;
376 
377  target.setRA(ra);
378  target.setDec(dec);
379 
380  return slew(&target);
381 }
382 
383 bool TelescopeLite::slew(SkyPoint *ScopeTarget)
384 {
385  auto motionSP = baseDevice->getSwitch("ON_COORD_SET");
386 
387  if (!motionSP)
388  return false;
389 
390  auto slewSW = motionSP->findWidgetByName("TRACK");
391 
392  if (!slewSW)
393  slewSW = motionSP->findWidgetByName("SLEW");
394 
395  if (!slewSW)
396  return false;
397 
398  if (slewSW->setState() != ISS_ON)
399  {
400  motionSP->reset();
401  slewSW->setState(ISS_ON);
402  clientManager->sendNewSwitch(motionSP);
403 
404  if (Options::iNDILogging())
405  qDebug() << "ISD:Telescope: " << slewSW->getName();
406  }
407 
408  return sendCoords(ScopeTarget);
409 }
410 
411 bool TelescopeLite::sync(double ra, double dec)
412 {
413  SkyPoint target;
414 
415  target.setRA(ra);
416  target.setDec(dec);
417 
418  return sync(&target);
419 }
420 
421 bool TelescopeLite::sync(SkyPoint *ScopeTarget)
422 {
423  auto motionSP = baseDevice->getSwitch("ON_COORD_SET");
424 
425  if (!motionSP)
426  return false;
427 
428  auto syncSW = motionSP->findWidgetByName("SYNC");
429 
430  if (!syncSW)
431  return false;
432 
433  if (syncSW->getState() != ISS_ON)
434  {
435  motionSP->reset();
436  syncSW->setState(ISS_ON);
437  clientManager->sendNewSwitch(motionSP);
438 
439  if (Options::iNDILogging())
440  qDebug() << "ISD:Telescope: Syncing...";
441  }
442 
443  return sendCoords(ScopeTarget);
444 }
445 
446 bool TelescopeLite::abort()
447 {
448  auto motionSP = baseDevice->getSwitch("TELESCOPE_ABORT_MOTION");
449 
450  if (!motionSP)
451  return false;
452 
453  auto abortSW = motionSP->findWidgetByName("ABORT");
454 
455  if (!abortSW)
456  return false;
457 
458  if (Options::iNDILogging())
459  qDebug() << "ISD:Telescope: Aborted." << endl;
460 
461  abortSW->setState(ISS_ON);
462  clientManager->sendNewSwitch(motionSP);
463 
464  return true;
465 }
466 
467 bool TelescopeLite::park()
468 {
469  auto parkSP = baseDevice->getSwitch("TELESCOPE_PARK");
470 
471  if (!parkSP)
472  return false;
473 
474  auto parkSW = parkSP->findWidgetByName("PARK");
475 
476  if (!parkSW)
477  return false;
478 
479  if (Options::iNDILogging())
480  qDebug() << "ISD:Telescope: Parking..." << endl;
481 
482  parkSP->reset();
483  parkSW->setState(ISS_ON);
484  clientManager->sendNewSwitch(parkSP);
485 
486  return true;
487 }
488 
489 bool TelescopeLite::unPark()
490 {
491  auto parkSP = baseDevice->getSwitch("TELESCOPE_PARK");
492 
493  if (!parkSP)
494  return false;
495 
496  auto parkSW = parkSP->findWidgetByName("UNPARK");
497 
498  if (!parkSW)
499  return false;
500 
501  if (Options::iNDILogging())
502  qDebug() << "ISD:Telescope: UnParking..." << endl;
503 
504  parkSP->reset();
505  parkSW->setState(ISS_ON);
506  clientManager->sendNewSwitch(parkSP);
507 
508  return true;
509 }
510 
511 bool TelescopeLite::getEqCoords(double *ra, double *dec)
512 {
513  auto EqProp = baseDevice->getNumber("EQUATORIAL_EOD_COORD");
514 
515  if (!EqProp)
516  return false;
517 
518  auto RAEle = EqProp->findWidgetByName("RA");
519  if (!RAEle)
520  return false;
521 
522  auto DecEle = EqProp->findWidgetByName("DEC");
523  if (!DecEle)
524  return false;
525 
526  *ra = RAEle->getValue();
527  *dec = DecEle->getValue();
528 
529  return true;
530 }
531 
532 bool TelescopeLite::moveNS(TelescopeMotionNS dir, TelescopeMotionCommand cmd)
533 {
534  auto motionSP = baseDevice->getSwitch("TELESCOPE_MOTION_NS");
535 
536  if (!motionSP)
537  return false;
538 
539  auto motionNorth = motionSP->findWidgetByName("MOTION_NORTH");
540  auto motionSouth = motionSP->findWidgetByName("MOTION_SOUTH");
541 
542  if (!motionNorth || !motionSouth)
543  return false;
544 
545  // If same direction, return
546  if (dir == MOTION_NORTH && motionNorth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
547  return true;
548 
549  if (dir == MOTION_SOUTH && motionSouth->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
550  return true;
551 
552  motionSP->reset();
553 
554  if (cmd == MOTION_START)
555  {
556  if (dir == MOTION_NORTH)
557  motionNorth->setState(ISS_ON);
558  else
559  motionSouth->setState(ISS_ON);
560  }
561 
562  if (cmd == MOTION_STOP)
563  {
564  if (dir == MOTION_NORTH)
565  motionNorth->setState(ISS_OFF);
566  else
567  motionSouth->setState(ISS_OFF);
568  }
569 
570  clientManager->sendNewSwitch(motionSP);
571 
572  return true;
573 }
574 
575 bool TelescopeLite::moveWE(TelescopeMotionWE dir, TelescopeMotionCommand cmd)
576 {
577  auto motionSP = baseDevice->getSwitch("TELESCOPE_MOTION_WE");
578 
579  if (motionSP == nullptr)
580  return false;
581 
582  auto motionWest = motionSP->findWidgetByName("MOTION_WEST");
583  auto motionEast = motionSP->findWidgetByName("MOTION_EAST");
584 
585  if (motionWest == nullptr || motionEast == nullptr)
586  return false;
587 
588  // If same direction, return
589  if (dir == MOTION_WEST && motionWest->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
590  return true;
591 
592  if (dir == MOTION_EAST && motionEast->getState() == ((cmd == MOTION_START) ? ISS_ON : ISS_OFF))
593  return true;
594 
595  IUResetSwitch(motionSP);
596 
597  if (cmd == MOTION_START)
598  {
599  if (dir == MOTION_WEST)
600  motionWest->setState(ISS_ON);
601  else
602  motionEast->setState(ISS_ON);
603  }
604 
605  if (cmd == MOTION_STOP)
606  {
607  if (dir == MOTION_WEST)
608  motionWest->setState(ISS_OFF);
609  else
610  motionEast->setState(ISS_OFF);
611  }
612 
613  clientManager->sendNewSwitch(motionSP);
614 
615  return true;
616 }
617 
618 bool TelescopeLite::setSlewRate(int index)
619 {
620  auto slewRateSP = baseDevice->getSwitch("TELESCOPE_SLEW_RATE");
621 
622  if (slewRateSP == nullptr)
623  return false;
624 
625  int maxSlewRate = slewRateSP->count();
626 
627  if (index < 0)
628  {
629  index = 0;
630  }
631  else if (index >= maxSlewRate)
632  {
633  index = maxSlewRate - 1;
634  }
635 
636  if (slewRateSP->at(index)->getState() != ISS_ON || index != slewRateIndex)
637  {
638  slewRateSP->reset();
639 
640  slewRateSP->at(index)->setState(ISS_ON);
641 
642  slewRateIndex = index;
643  setSlewRateLabel(slewRateSP->at(index)->getLabel());
644  setSlewDecreasable(index != 0);
645  setSlewIncreasable(index != maxSlewRate - 1);
646 
647  clientManager->sendNewSwitch(slewRateSP);
648  }
649 
650  return true;
651 }
652 
653 bool TelescopeLite::decreaseSlewRate()
654 {
655  return setSlewRate(slewRateIndex - 1);
656 }
657 
658 bool TelescopeLite::increaseSlewRate()
659 {
660  return setSlewRate(slewRateIndex + 1);
661 }
662 
663 void TelescopeLite::setAltLimits(double minAltitude, double maxAltitude)
664 {
665  minAlt = minAltitude;
666  maxAlt = maxAltitude;
667 }
668 
669 bool TelescopeLite::isParked()
670 {
671  return IsParked;
672 }
const dms & alt() const
Definition: skypoint.h:281
This class loads QML files and connects SkyMapLite and KStarsData Unlike KStars class it is not a mai...
Definition: kstarslite.h:46
QTextStream & endl(QTextStream &stream)
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
void setDec0(dms d)
Sets Dec0, the catalog Declination.
Definition: skypoint.h:119
static KStarsLite * Instance()
Definition: kstarslite.h:77
void setRA0(dms r)
Sets RA0, the catalog Right Ascension.
Definition: skypoint.h:94
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition: skypoint.cpp:77
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
dms altRefracted() const
Definition: skypoint.cpp:1050
const CachingDms & dec() const
Definition: skypoint.h:269
void reset()
QTextStream & dec(QTextStream &stream)
GeoCoordinates geo(const QVariant &location)
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
const CachingDms & ra() const
Definition: skypoint.h:263
void apparentCoord(long double jd0, long double jdf)
Computes the apparent coordinates for this SkyPoint for any epoch, accounting for the effects of prec...
Definition: skypoint.cpp:700
const CachingDms & dec0() const
Definition: skypoint.h:257
const double & Degrees() const
Definition: dms.h:141
const CachingDms & ra0() const
Definition: skypoint.h:251
void setDec(dms d)
Sets Dec, the current Declination.
Definition: skypoint.h:169
void setRA(dms &r)
Sets RA, the current Right Ascension.
Definition: skypoint.h:144
double Hours() const
Definition: dms.h:168
const dms & az() const
Definition: skypoint.h:275
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 15 2022 04:04:02 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.