Kstars

indidome.cpp
1/*
2 SPDX-FileCopyrightText: 2015 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include <basedevice.h>
8#include <KActionCollection>
9#include <KNotification>
10#include <QAction>
11#include <QtDBus/qdbusmetatype.h>
12
13#include "indidome.h"
14#include "kstars.h"
15#include "domeadaptor.h"
16#include "ksnotification.h"
17
18namespace ISD
19{
20
21const QList<KLocalizedString> Dome::domeStates = { ki18n("Idle"), ki18n("Moving clockwise"), ki18n("Moving counter clockwise"),
22 ki18n("Tracking"), ki18n("Parking"), ki18n("UnParking"), ki18n("Parked"),
23 ki18n("Error")
24 };
25
26Dome::Dome(GenericDevice *parent) : ConcreteDevice(parent)
27{
28 qRegisterMetaType<ISD::Dome::Status>("ISD::Dome::Status");
29 qDBusRegisterMetaType<ISD::Dome::Status>();
30
31 qRegisterMetaType<ISD::Dome::ShutterStatus>("ISD::Dome::ShutterStatus");
32 qDBusRegisterMetaType<ISD::Dome::ShutterStatus>();
33
34 new DomeAdaptor(this);
35 m_DBusObjectPath = QString("/KStars/INDI/Dome/%1").arg(getID());
36 QDBusConnection::sessionBus().registerObject(m_DBusObjectPath, this);
37}
38
39void Dome::registerProperty(INDI::Property prop)
40{
41 if (!prop.getRegistered())
42 return;
43
44 if (prop.isNameMatch("ABS_DOME_POSITION"))
45 {
46 m_CanAbsMove = true;
47 }
48 else if (prop.isNameMatch("REL_DOME_POSITION"))
49 {
50 m_CanRelMove = true;
51 }
52 else if (prop.isNameMatch("DOME_ABORT_MOTION"))
53 {
54 m_CanAbort = true;
55 }
56 else if (prop.isNameMatch("DOME_PARK"))
57 {
58 m_CanPark = true;
59 }
60 else if (prop.isNameMatch("DOME_SHUTTER"))
61 {
62 m_HasShutter = true;
63 }
64
65 ConcreteDevice::registerProperty(prop);
66}
67
68void Dome::processNumber(INDI::Property prop)
69{
70 auto nvp = prop.getNumber();
71 if (nvp->isNameMatch("ABS_DOME_POSITION"))
72 {
73 emit positionChanged(nvp->at(0)->getValue());
74 }
75}
76
77void Dome::processSwitch(INDI::Property prop)
78{
79 auto svp = prop.getSwitch();
80 if (svp->isNameMatch("CONNECTION"))
81 {
82 auto conSP = svp->findWidgetByName("CONNECT");
83 if (conSP)
84 {
85 if (conSP->getState() == ISS_ON)
87 else
88 {
90
91 m_CanAbsMove = false;
92 m_CanPark = false;
93 }
94 }
95 }
96 else if (svp->isNameMatch("DOME_PARK"))
97 {
98 m_CanPark = true;
99
100 auto sp = svp->findWidgetByName("PARK");
101 if (sp)
102 {
103 if (svp->getState() == IPS_ALERT)
104 {
105 m_ParkStatus = PARK_ERROR;
106 emit newParkStatus(PARK_ERROR);
107
108 // If alert, set park status to whatever it was opposite to. That is, if it was parking and failed
109 // then we set status to unparked since it did not successfully complete parking.
110 // if (m_ParkStatus == PARK_PARKING)
111 // m_ParkStatus = PARK_UNPARKED;
112 // else if (m_ParkStatus == PARK_UNPARKING)
113 // m_ParkStatus = PARK_PARKED;
114
115 // emit newParkStatus(m_ParkStatus);
116
117 }
118 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKING)
119 {
120 m_ParkStatus = PARK_PARKING;
121 KSNotification::event(QLatin1String("DomeParking"), i18n("Dome parking is in progress"), KSNotification::Observatory,
122 KSNotification::Info);
123 emit newParkStatus(m_ParkStatus);
124
125 if (m_Status != DOME_PARKING)
126 {
127 m_Status = DOME_PARKING;
128 emit newStatus(m_Status);
129 }
130 }
131 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_OFF && m_ParkStatus != PARK_UNPARKING)
132 {
133 m_ParkStatus = PARK_UNPARKING;
134 KSNotification::event(QLatin1String("DomeUnparking"), i18n("Dome unparking is in progress"), KSNotification::Observatory,
135 KSNotification::Info);
136 emit newParkStatus(m_ParkStatus);
137
138 if (m_Status != DOME_UNPARKING)
139 {
140 m_Status = DOME_UNPARKING;
141 emit newStatus(m_Status);
142 }
143 }
144 else if (svp->getState() == IPS_OK && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKED)
145 {
146 m_ParkStatus = PARK_PARKED;
147 KSNotification::event(QLatin1String("DomeParked"), i18n("Dome parked"), KSNotification::Observatory,
148 KSNotification::Info);
149 emit newParkStatus(m_ParkStatus);
150
151 QAction *parkAction = KStars::Instance()->actionCollection()->action("dome_park");
152 if (parkAction)
153 parkAction->setEnabled(false);
154 QAction *unParkAction = KStars::Instance()->actionCollection()->action("dome_unpark");
155 if (unParkAction)
156 unParkAction->setEnabled(true);
157
158 if (m_Status != DOME_PARKED)
159 {
160 m_Status = DOME_PARKED;
161 emit newStatus(m_Status);
162 }
163
164 }
165 else if ( (svp->getState() == IPS_OK || svp->getState() == IPS_IDLE) && sp->s == ISS_OFF && m_ParkStatus != PARK_UNPARKED)
166 {
167 m_ParkStatus = PARK_UNPARKED;
168 KSNotification::event(QLatin1String("DomeUnparked"), i18n("Dome unparked"), KSNotification::Observatory,
169 KSNotification::Info);
170
171 QAction *parkAction = KStars::Instance()->actionCollection()->action("dome_park");
172 if (parkAction)
173 parkAction->setEnabled(true);
174 QAction *unParkAction = KStars::Instance()->actionCollection()->action("dome_unpark");
175 if (unParkAction)
176 unParkAction->setEnabled(false);
177
178 emit newParkStatus(m_ParkStatus);
179
180 if (m_Status != DOME_IDLE)
181 {
182 m_Status = DOME_IDLE;
183 emit newStatus(m_Status);
184 }
185 }
186 }
187 }
188 else if (svp->isNameMatch("DOME_MOTION"))
189 {
190 Status lastStatus = m_Status;
191
192 if (svp->getState() == IPS_BUSY && lastStatus != DOME_MOVING_CW && lastStatus != DOME_MOVING_CCW
193 && lastStatus != DOME_PARKING
194 && lastStatus != DOME_UNPARKING)
195 {
196 m_Status = svp->at(0)->getState() == ISS_ON ? DOME_MOVING_CW : DOME_MOVING_CCW;
197 emit newStatus(m_Status);
198
199 // rolloff roofs: cw = opening = unparking, ccw = closing = parking
200 if (!canAbsoluteMove() && !canRelativeMove())
201 {
202 m_ParkStatus = (m_Status == DOME_MOVING_CW) ? PARK_UNPARKING : PARK_PARKING;
203 emit newParkStatus(m_ParkStatus);
204 }
205 }
206 else if (svp->getState() == IPS_OK && (lastStatus == DOME_MOVING_CW || lastStatus == DOME_MOVING_CCW))
207 {
208 m_Status = DOME_TRACKING;
209 emit newStatus(m_Status);
210 }
211 else if (svp->getState() == IPS_IDLE && lastStatus != DOME_IDLE)
212 {
213 m_Status = DOME_IDLE;
214 emit newStatus(m_Status);
215 }
216 else if (svp->getState() == IPS_ALERT)
217 {
218 m_Status = DOME_ERROR;
219 emit newStatus(m_Status);
220 }
221 }
222 else if (svp->isNameMatch("DOME_SHUTTER"))
223 {
224 if (svp->getState() == IPS_ALERT)
225 {
226 emit newShutterStatus(SHUTTER_ERROR);
227
228 // If alert, set shutter status to whatever it was opposite to. That is, if it was opening and failed
229 // then we set status to closed since it did not successfully complete opening.
230 if (m_ShutterStatus == SHUTTER_CLOSING)
231 m_ShutterStatus = SHUTTER_OPEN;
232 else
233 m_ShutterStatus = SHUTTER_CLOSED;
234
235 emit newShutterStatus(m_ShutterStatus);
236 }
237
238 ShutterStatus status = parseShutterStatus(prop);
239
240 switch (status)
241 {
242 case SHUTTER_CLOSING:
243 if (m_ShutterStatus != SHUTTER_CLOSING)
244 {
245 m_ShutterStatus = SHUTTER_CLOSING;
246 KSNotification::event(QLatin1String("ShutterClosing"), i18n("Shutter closing is in progress"), KSNotification::Observatory,
247 KSNotification::Info);
248 emit newShutterStatus(m_ShutterStatus);
249 }
250 break;
251 case SHUTTER_OPENING:
252 if (m_ShutterStatus != SHUTTER_OPENING)
253 {
254 m_ShutterStatus = SHUTTER_OPENING;
255 KSNotification::event(QLatin1String("ShutterOpening"), i18n("Shutter opening is in progress"), KSNotification::Observatory,
256 KSNotification::Info);
257 emit newShutterStatus(m_ShutterStatus);
258 }
259 break;
260 case SHUTTER_CLOSED:
261 if (m_ShutterStatus != SHUTTER_CLOSED)
262 {
263 m_ShutterStatus = SHUTTER_CLOSED;
264 KSNotification::event(QLatin1String("ShutterClosed"), i18n("Shutter closed"), KSNotification::Observatory,
265 KSNotification::Info);
266 emit newShutterStatus(m_ShutterStatus);
267 }
268 break;
269 case SHUTTER_OPEN:
270 if (m_ShutterStatus != SHUTTER_OPEN)
271 {
272 m_ShutterStatus = SHUTTER_OPEN;
273 KSNotification::event(QLatin1String("ShutterOpened"), i18n("Shutter opened"), KSNotification::Observatory,
274 KSNotification::Info);
275 emit newShutterStatus(m_ShutterStatus);
276 }
277 break;
278 default:
279 break;
280 }
281
282 return;
283
284 }
285 else if (svp->isNameMatch("DOME_AUTOSYNC"))
286 {
287 auto sp = svp->findWidgetByName("DOME_AUTOSYNC_ENABLE");
288 if (sp != nullptr)
289 emit newAutoSyncStatus(sp->s == ISS_ON);
290 }
291}
292
293bool Dome::abort()
294{
295 if (m_CanAbort == false)
296 return false;
297
298 auto motionSP = getSwitch("DOME_ABORT_MOTION");
299
300 if (!motionSP)
301 return false;
302
303 auto abortSW = motionSP->findWidgetByName("ABORT");
304
305 if (!abortSW)
306 return false;
307
308 abortSW->setState(ISS_ON);
309 sendNewProperty(motionSP);
310
311 return true;
312}
313
314bool Dome::park()
315{
316 auto parkSP = getSwitch("DOME_PARK");
317
318 if (!parkSP)
319 return false;
320
321 auto parkSW = parkSP->findWidgetByName("PARK");
322
323 if (!parkSW)
324 return false;
325
326 parkSP->reset();
327 parkSW->setState(ISS_ON);
328 sendNewProperty(parkSP);
329
330 return true;
331}
332
333bool Dome::unpark()
334{
335 auto parkSP = getSwitch("DOME_PARK");
336
337 if (!parkSP)
338 return false;
339
340 auto parkSW = parkSP->findWidgetByName("UNPARK");
341
342 if (!parkSW)
343 return false;
344
345 parkSP->reset();
346 parkSW->setState(ISS_ON);
347 sendNewProperty(parkSP);
348
349 return true;
350}
351
352bool Dome::isMoving() const
353{
354 auto motionSP = getSwitch("DOME_MOTION");
355
356 if (motionSP && motionSP->getState() == IPS_BUSY)
357 return true;
358
359 return false;
360}
361
362double Dome::position() const
363{
364 auto az = getNumber("ABS_DOME_POSITION");
365
366 if (!az)
367 return -1;
368 else
369 return az->at(0)->getValue();
370}
371
372bool Dome::setPosition(double position)
373{
374 auto az = getNumber("ABS_DOME_POSITION");
375
376 if (!az)
377 return false;
378
379 az->at(0)->setValue(position);
380 sendNewProperty(az);
381 return true;
382}
383
384bool Dome::setRelativePosition(double position)
385{
386 auto azDiff = getNumber("REL_DOME_POSITION");
387 if (!azDiff)
388 return false;
389
390 azDiff->at(0)->setValue(position);
391 sendNewProperty(azDiff);
392 return true;
393}
394
395bool Dome::isAutoSync()
396{
397 auto autosync = getSwitch("DOME_AUTOSYNC");
398 if (!autosync)
399 return false;
400
401 auto autosyncSW = autosync->findWidgetByName("DOME_AUTOSYNC_ENABLE");
402 if (!autosyncSW)
403 return false;
404 else
405 return (autosyncSW->s == ISS_ON);
406}
407
408bool Dome::setAutoSync(bool activate)
409{
410 auto autosync = getSwitch("DOME_AUTOSYNC");
411 if (!autosync)
412 return false;
413
414 auto autosyncSW = autosync->findWidgetByName(activate ? "DOME_AUTOSYNC_ENABLE" : "DOME_AUTOSYNC_DISABLE");
415 if (!autosyncSW)
416 return false;
417
418 autosync->reset();
419 autosyncSW->setState(ISS_ON);
420 sendNewProperty(autosync);
421
422 return true;
423}
424
425bool Dome::moveDome(DomeDirection dir, DomeMotionCommand operation)
426{
427 auto domeMotion = getSwitch("DOME_MOTION");
428 if (!domeMotion)
429 return false;
430
431 auto opSwitch = domeMotion->findWidgetByName(dir == DomeDirection::DOME_CW ? "DOME_CW" : "DOME_CCW");
432 if (!opSwitch)
433 return false;
434
435 domeMotion->reset();
436 opSwitch->setState(operation == DomeMotionCommand::MOTION_START ? ISS_ON : ISS_OFF);
437 sendNewProperty(domeMotion);
438 return true;
439}
440
441bool Dome::controlShutter(bool open)
442{
443 auto shutterSP = getSwitch("DOME_SHUTTER");
444 if (!shutterSP)
445 return false;
446
447 auto shutterSW = shutterSP->findWidgetByName(open ? "SHUTTER_OPEN" : "SHUTTER_CLOSE");
448 if (!shutterSW)
449 return false;
450
451 shutterSP->reset();
452 shutterSW->setState(ISS_ON);
453 sendNewProperty(shutterSP);
454
455 return true;
456}
457
458Dome::ShutterStatus Dome::shutterStatus()
459{
460 auto shutterSP = getSwitch("DOME_SHUTTER");
461
462 return parseShutterStatus(shutterSP);
463}
464
465Dome::ShutterStatus Dome::parseShutterStatus(INDI::Property prop)
466{
467 if (prop.isValid() == false)
468 return SHUTTER_UNKNOWN;
469
470 auto svp = prop.getSwitch();
471
472 auto sp = svp->findWidgetByName("SHUTTER_OPEN");
473 if (sp == nullptr)
474 return SHUTTER_UNKNOWN;
475
476 if (svp->getState() == IPS_ALERT)
477 return SHUTTER_ERROR;
478 else if (svp->getState() == IPS_BUSY)
479 return (sp->s == ISS_ON) ? SHUTTER_OPENING : SHUTTER_CLOSING;
480 else if (svp->getState() == IPS_OK)
481 return (sp->s == ISS_ON) ? SHUTTER_OPEN : SHUTTER_CLOSED;
482
483 // this should not happen
484 return SHUTTER_UNKNOWN;
485}
486
487const QString Dome::getStatusString(Dome::Status status, bool translated)
488{
489 return translated ? domeStates[status].toString() : domeStates[status].untranslatedText();
490}
491
492}
493
494QDBusArgument &operator<<(QDBusArgument &argument, const ISD::Dome::Status &source)
495{
496 argument.beginStructure();
497 argument << static_cast<int>(source);
498 argument.endStructure();
499 return argument;
500}
501
502const QDBusArgument &operator>>(const QDBusArgument &argument, ISD::Dome::Status &dest)
503{
504 int a;
505 argument.beginStructure();
506 argument >> a;
507 argument.endStructure();
508 dest = static_cast<ISD::Dome::Status>(a);
509 return argument;
510}
511
512QDBusArgument &operator<<(QDBusArgument &argument, const ISD::Dome::ShutterStatus &source)
513{
514 argument.beginStructure();
515 argument << static_cast<int>(source);
516 argument.endStructure();
517 return argument;
518}
519
520const QDBusArgument &operator>>(const QDBusArgument &argument, ISD::Dome::ShutterStatus &dest)
521{
522 int a;
523 argument.beginStructure();
524 argument >> a;
525 argument.endStructure();
526 dest = static_cast<ISD::Dome::ShutterStatus>(a);
527 return argument;
528}
529
531{
532 auto nvp = getNumber("DOME_MEASUREMENTS");
533 if (nvp)
534 {
535 auto radius = nvp->findWidgetByName("DM_DOME_RADIUS");
536 if (radius)
537 return radius->getValue();
538 }
539 return 0;
540}
541
543{
544 auto nvp = getNumber("DOME_MEASUREMENTS");
545 if (nvp)
546 {
547 auto width = nvp->findWidgetByName("DM_SHUTTER_WIDTH");
548 if (width)
549 return width->getValue();
550 }
551 return 0;
552}
553
555{
556 auto nvp = getNumber("DOME_MEASUREMENTS");
557 if (nvp)
558 {
559 auto north = nvp->findWidgetByName("DM_NORTH_DISPLACEMENT");
560 if (north)
561 return north->getValue();
562 }
563 return 0;
564}
565
567{
568 auto nvp = getNumber("DOME_MEASUREMENTS");
569 if (nvp)
570 {
571 auto east = nvp->findWidgetByName("DM_EAST_DISPLACEMENT");
572 if (east)
573 return east->getValue();
574 }
575 return 0;
576}
577
579{
580 auto nvp = getNumber("DOME_MEASUREMENTS");
581 if (nvp)
582 {
583 auto up = nvp->findWidgetByName("DM_UP_DISPLACEMENT");
584 if (up)
585 return up->getValue();
586 }
587 return 0;
588}
589
591{
592 auto nvp = getNumber("DOME_MEASUREMENTS");
593 if (nvp)
594 {
595 auto ota = nvp->findWidgetByName("DM_OTA_OFFSET");
596 if (ota)
597 return ota->getValue();
598 }
599 return 0;
600}
The ConcreteDevice class.
void sendNewProperty(INDI::Property prop)
Send new property command to server.
double getNorthDisplacement() const
getNorthDisplacement Get the north displacement in meters
Definition indidome.cpp:554
double getDomeRadius() const
getDomeRadius Get the dome radius in meters
Definition indidome.cpp:530
Q_SCRIPTABLE bool setPosition(double position)
setPosition Set azimuth absolute position.
Definition indidome.cpp:372
double getOTAOffset() const
getOTAOffset Get the OTA offset in meters
Definition indidome.cpp:590
double getShutterWidth() const
getShutterWidth Get the shutter width in meters
Definition indidome.cpp:542
double getEastDisplacement() const
getEastDisplacement Get the east displacement in meters
Definition indidome.cpp:566
double getUpDisplacement() const
getUpDisplacement Get the up displacement in meters
Definition indidome.cpp:578
GenericDevice is the Generic Device for INDI devices.
Definition indistd.h:117
Q_INVOKABLE QAction * action(const QString &name) const
static KStars * Instance()
Definition kstars.h:122
void slotSetDomeEnabled(bool enable)
slotSetDomeEnabled call when dome comes online or goes offline.
virtual KActionCollection * actionCollection() const
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18n(const char *text, const TYPE &arg...)
ISD is a collection of INDI Standard Devices.
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void setEnabled(bool)
void beginStructure()
void endStructure()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
QString arg(Args &&... args) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:57:25 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.