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 <qdbusmetatype.h>
12
13#include "indidome.h"
14#include "kstars.h"
15#include "domeadaptor.h"
16
17namespace ISD
18{
19
20const QList<const char *> Dome::domeStates = { I18N_NOOP("Idle"), I18N_NOOP("Moving clockwise"), I18N_NOOP("Moving counter clockwise"),
21 I18N_NOOP("Tracking"), I18N_NOOP("Parking"), I18N_NOOP("UnParking"), I18N_NOOP("Parked"),
22 I18N_NOOP("Error")
23 };
24
25Dome::Dome(GenericDevice *parent) : ConcreteDevice(parent)
26{
27 qRegisterMetaType<ISD::Dome::Status>("ISD::Dome::Status");
29
30 qRegisterMetaType<ISD::Dome::ShutterStatus>("ISD::Dome::ShutterStatus");
32
33 new DomeAdaptor(this);
34 m_DBusObjectPath = QString("/KStars/INDI/Dome/%1").arg(getID());
35 QDBusConnection::sessionBus().registerObject(m_DBusObjectPath, this);
36}
37
38void Dome::registerProperty(INDI::Property prop)
39{
40 if (!prop.getRegistered())
41 return;
42
43 if (prop.isNameMatch("ABS_DOME_POSITION"))
44 {
45 m_CanAbsMove = true;
46 }
47 else if (prop.isNameMatch("REL_DOME_POSITION"))
48 {
49 m_CanRelMove = true;
50 }
51 else if (prop.isNameMatch("DOME_ABORT_MOTION"))
52 {
53 m_CanAbort = true;
54 }
55 else if (prop.isNameMatch("DOME_PARK"))
56 {
57 m_CanPark = true;
58 }
59 else if (prop.isNameMatch("DOME_SHUTTER"))
60 {
61 m_HasShutter = true;
62 }
63
64 ConcreteDevice::registerProperty(prop);
65}
66
67void Dome::processNumber(INDI::Property prop)
68{
69 auto nvp = prop.getNumber();
70 if (nvp->isNameMatch("ABS_DOME_POSITION"))
71 {
72 emit positionChanged(nvp->at(0)->getValue());
73 }
74}
75
76void Dome::processSwitch(INDI::Property prop)
77{
78 auto svp = prop.getSwitch();
79 if (svp->isNameMatch("CONNECTION"))
80 {
81 auto conSP = svp->findWidgetByName("CONNECT");
82 if (conSP)
83 {
84 if (conSP->getState() == ISS_ON)
85 KStars::Instance()->slotSetDomeEnabled(true);
86 else
87 {
88 KStars::Instance()->slotSetDomeEnabled(false);
89
90 m_CanAbsMove = false;
91 m_CanPark = false;
92 }
93 }
94 }
95 else if (svp->isNameMatch("DOME_PARK"))
96 {
97 m_CanPark = true;
98
99 auto sp = svp->findWidgetByName("PARK");
100 if (sp)
101 {
102 if (svp->getState() == IPS_ALERT)
103 {
104 m_ParkStatus = PARK_ERROR;
105 emit newParkStatus(PARK_ERROR);
106
107 // If alert, set park status to whatever it was opposite to. That is, if it was parking and failed
108 // then we set status to unparked since it did not successfully complete parking.
109 // if (m_ParkStatus == PARK_PARKING)
110 // m_ParkStatus = PARK_UNPARKED;
111 // else if (m_ParkStatus == PARK_UNPARKING)
112 // m_ParkStatus = PARK_PARKED;
113
114 // emit newParkStatus(m_ParkStatus);
115
116 }
117 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKING)
118 {
119 m_ParkStatus = PARK_PARKING;
120 KNotification::event(QLatin1String("DomeParking"), i18n("Dome parking is in progress"));
121 emit newParkStatus(m_ParkStatus);
122
123 if (m_Status != DOME_PARKING)
124 {
125 m_Status = DOME_PARKING;
126 emit newStatus(m_Status);
127 }
128 }
129 else if (svp->getState() == IPS_BUSY && sp->getState() == ISS_OFF && m_ParkStatus != PARK_UNPARKING)
130 {
131 m_ParkStatus = PARK_UNPARKING;
132 KNotification::event(QLatin1String("DomeUnparking"), i18n("Dome unparking is in progress"));
133 emit newParkStatus(m_ParkStatus);
134
135 if (m_Status != DOME_UNPARKING)
136 {
137 m_Status = DOME_UNPARKING;
138 emit newStatus(m_Status);
139 }
140 }
141 else if (svp->getState() == IPS_OK && sp->getState() == ISS_ON && m_ParkStatus != PARK_PARKED)
142 {
143 m_ParkStatus = PARK_PARKED;
144 KNotification::event(QLatin1String("DomeParked"), i18n("Dome parked"));
145 emit newParkStatus(m_ParkStatus);
146
147 QAction *parkAction = KStars::Instance()->actionCollection()->action("dome_park");
148 if (parkAction)
149 parkAction->setEnabled(false);
150 QAction *unParkAction = KStars::Instance()->actionCollection()->action("dome_unpark");
151 if (unParkAction)
152 unParkAction->setEnabled(true);
153
154 if (m_Status != DOME_PARKED)
155 {
156 m_Status = DOME_PARKED;
157 emit newStatus(m_Status);
158 }
159
160 }
161 else if ( (svp->getState() == IPS_OK || svp->getState() == IPS_IDLE) && sp->s == ISS_OFF && m_ParkStatus != PARK_UNPARKED)
162 {
163 m_ParkStatus = PARK_UNPARKED;
164 KNotification::event(QLatin1String("DomeUnparked"), i18n("Dome unparked"));
165
166 QAction *parkAction = KStars::Instance()->actionCollection()->action("dome_park");
167 if (parkAction)
168 parkAction->setEnabled(true);
169 QAction *unParkAction = KStars::Instance()->actionCollection()->action("dome_unpark");
170 if (unParkAction)
171 unParkAction->setEnabled(false);
172
173 emit newParkStatus(m_ParkStatus);
174
175 if (m_Status != DOME_IDLE)
176 {
177 m_Status = DOME_IDLE;
178 emit newStatus(m_Status);
179 }
180 }
181 }
182 }
183 else if (svp->isNameMatch("DOME_MOTION"))
184 {
185 Status lastStatus = m_Status;
186
187 if (svp->getState() == IPS_BUSY && lastStatus != DOME_MOVING_CW && lastStatus != DOME_MOVING_CCW
188 && lastStatus != DOME_PARKING
189 && lastStatus != DOME_UNPARKING)
190 {
191 m_Status = svp->at(0)->getState() == ISS_ON ? DOME_MOVING_CW : DOME_MOVING_CCW;
192 emit newStatus(m_Status);
193
194 // rolloff roofs: cw = opening = unparking, ccw = closing = parking
195 if (!canAbsoluteMove() && !canRelativeMove())
196 {
197 m_ParkStatus = (m_Status == DOME_MOVING_CW) ? PARK_UNPARKING : PARK_PARKING;
198 emit newParkStatus(m_ParkStatus);
199 }
200 }
201 else if (svp->getState() == IPS_OK && (lastStatus == DOME_MOVING_CW || lastStatus == DOME_MOVING_CCW))
202 {
203 m_Status = DOME_TRACKING;
204 emit newStatus(m_Status);
205 }
206 else if (svp->getState() == IPS_IDLE && lastStatus != DOME_IDLE)
207 {
208 m_Status = DOME_IDLE;
209 emit newStatus(m_Status);
210 }
211 else if (svp->getState() == IPS_ALERT)
212 {
213 m_Status = DOME_ERROR;
214 emit newStatus(m_Status);
215 }
216 }
217 else if (svp->isNameMatch("DOME_SHUTTER"))
218 {
219 if (svp->getState() == IPS_ALERT)
220 {
221 emit newShutterStatus(SHUTTER_ERROR);
222
223 // If alert, set shutter status to whatever it was opposite to. That is, if it was opening and failed
224 // then we set status to closed since it did not successfully complete opening.
225 if (m_ShutterStatus == SHUTTER_CLOSING)
226 m_ShutterStatus = SHUTTER_OPEN;
227 else
228 m_ShutterStatus = SHUTTER_CLOSED;
229
230 emit newShutterStatus(m_ShutterStatus);
231 }
232
233 ShutterStatus status = parseShutterStatus(prop);
234
235 switch (status)
236 {
237 case SHUTTER_CLOSING:
238 if (m_ShutterStatus != SHUTTER_CLOSING)
239 {
240 m_ShutterStatus = SHUTTER_CLOSING;
241 KNotification::event(QLatin1String("ShutterClosing"), i18n("Shutter closing is in progress"));
242 emit newShutterStatus(m_ShutterStatus);
243 }
244 break;
245 case SHUTTER_OPENING:
246 if (m_ShutterStatus != SHUTTER_OPENING)
247 {
248 m_ShutterStatus = SHUTTER_OPENING;
249 KNotification::event(QLatin1String("ShutterOpening"), i18n("Shutter opening is in progress"));
250 emit newShutterStatus(m_ShutterStatus);
251 }
252 break;
253 case SHUTTER_CLOSED:
254 if (m_ShutterStatus != SHUTTER_CLOSED)
255 {
256 m_ShutterStatus = SHUTTER_CLOSED;
257 KNotification::event(QLatin1String("ShutterClosed"), i18n("Shutter closed"));
258 emit newShutterStatus(m_ShutterStatus);
259 }
260 break;
261 case SHUTTER_OPEN:
262 if (m_ShutterStatus != SHUTTER_OPEN)
263 {
264 m_ShutterStatus = SHUTTER_OPEN;
265 KNotification::event(QLatin1String("ShutterOpened"), i18n("Shutter opened"));
266 emit newShutterStatus(m_ShutterStatus);
267 }
268 break;
269 default:
270 break;
271 }
272
273 return;
274
275 }
276 else if (svp->isNameMatch("DOME_AUTOSYNC"))
277 {
278 auto sp = svp->findWidgetByName("DOME_AUTOSYNC_ENABLE");
279 if (sp != nullptr)
280 emit newAutoSyncStatus(sp->s == ISS_ON);
281 }
282}
283
284bool Dome::abort()
285{
286 if (m_CanAbort == false)
287 return false;
288
289 auto motionSP = getSwitch("DOME_ABORT_MOTION");
290
291 if (!motionSP)
292 return false;
293
294 auto abortSW = motionSP->findWidgetByName("ABORT");
295
296 if (!abortSW)
297 return false;
298
299 abortSW->setState(ISS_ON);
300 sendNewProperty(motionSP);
301
302 return true;
303}
304
305bool Dome::park()
306{
307 auto parkSP = getSwitch("DOME_PARK");
308
309 if (!parkSP)
310 return false;
311
312 auto parkSW = parkSP->findWidgetByName("PARK");
313
314 if (!parkSW)
315 return false;
316
317 parkSP->reset();
318 parkSW->setState(ISS_ON);
319 sendNewProperty(parkSP);
320
321 return true;
322}
323
324bool Dome::unpark()
325{
326 auto parkSP = getSwitch("DOME_PARK");
327
328 if (!parkSP)
329 return false;
330
331 auto parkSW = parkSP->findWidgetByName("UNPARK");
332
333 if (!parkSW)
334 return false;
335
336 parkSP->reset();
337 parkSW->setState(ISS_ON);
338 sendNewProperty(parkSP);
339
340 return true;
341}
342
343bool Dome::isMoving() const
344{
345 auto motionSP = getSwitch("DOME_MOTION");
346
347 if (motionSP && motionSP->getState() == IPS_BUSY)
348 return true;
349
350 return false;
351}
352
353double Dome::position() const
354{
355 auto az = getNumber("ABS_DOME_POSITION");
356
357 if (!az)
358 return -1;
359 else
360 return az->at(0)->getValue();
361}
362
363bool Dome::setPosition(double position)
364{
365 auto az = getNumber("ABS_DOME_POSITION");
366
367 if (!az)
368 return false;
369
370 az->at(0)->setValue(position);
371 sendNewProperty(az);
372 return true;
373}
374
375bool Dome::setRelativePosition(double position)
376{
377 auto azDiff = getNumber("REL_DOME_POSITION");
378 if (!azDiff)
379 return false;
380
381 azDiff->at(0)->setValue(position);
382 sendNewProperty(azDiff);
383 return true;
384}
385
386bool Dome::isAutoSync()
387{
388 auto autosync = getSwitch("DOME_AUTOSYNC");
389 if (!autosync)
390 return false;
391
392 auto autosyncSW = autosync->findWidgetByName("DOME_AUTOSYNC_ENABLE");
393 if (!autosyncSW)
394 return false;
395 else
396 return (autosyncSW->s == ISS_ON);
397}
398
399bool Dome::setAutoSync(bool activate)
400{
401 auto autosync = getSwitch("DOME_AUTOSYNC");
402 if (!autosync)
403 return false;
404
405 auto autosyncSW = autosync->findWidgetByName(activate ? "DOME_AUTOSYNC_ENABLE" : "DOME_AUTOSYNC_DISABLE");
406 if (!autosyncSW)
407 return false;
408
409 autosync->reset();
410 autosyncSW->setState(ISS_ON);
411 sendNewProperty(autosync);
412
413 return true;
414}
415
416bool Dome::moveDome(DomeDirection dir, DomeMotionCommand operation)
417{
418 auto domeMotion = getSwitch("DOME_MOTION");
419 if (!domeMotion)
420 return false;
421
422 auto opSwitch = domeMotion->findWidgetByName(dir == DomeDirection::DOME_CW ? "DOME_CW" : "DOME_CCW");
423 if (!opSwitch)
424 return false;
425
426 domeMotion->reset();
427 opSwitch->setState(operation == DomeMotionCommand::MOTION_START ? ISS_ON : ISS_OFF);
428 sendNewProperty(domeMotion);
429 return true;
430}
431
432bool Dome::controlShutter(bool open)
433{
434 auto shutterSP = getSwitch("DOME_SHUTTER");
435 if (!shutterSP)
436 return false;
437
438 auto shutterSW = shutterSP->findWidgetByName(open ? "SHUTTER_OPEN" : "SHUTTER_CLOSE");
439 if (!shutterSW)
440 return false;
441
442 shutterSP->reset();
443 shutterSW->setState(ISS_ON);
444 sendNewProperty(shutterSP);
445
446 return true;
447}
448
449Dome::ShutterStatus Dome::shutterStatus()
450{
451 auto shutterSP = getSwitch("DOME_SHUTTER");
452
453 return parseShutterStatus(shutterSP);
454}
455
456Dome::ShutterStatus Dome::parseShutterStatus(INDI::Property prop)
457{
458 if (prop.isValid() == false)
459 return SHUTTER_UNKNOWN;
460
461 auto svp = prop.getSwitch();
462
463 auto sp = svp->findWidgetByName("SHUTTER_OPEN");
464 if (sp == nullptr)
465 return SHUTTER_UNKNOWN;
466
467 if (svp->getState() == IPS_ALERT)
468 return SHUTTER_ERROR;
469 else if (svp->getState() == IPS_BUSY)
470 return (sp->s == ISS_ON) ? SHUTTER_OPENING : SHUTTER_CLOSING;
471 else if (svp->getState() == IPS_OK)
472 return (sp->s == ISS_ON) ? SHUTTER_OPEN : SHUTTER_CLOSED;
473
474 // this should not happen
475 return SHUTTER_UNKNOWN;
476}
477
478const QString Dome::getStatusString(Dome::Status status, bool translated)
479{
480 return translated ? i18n(domeStates[status]) : domeStates[status];
481}
482
483}
484
485QDBusArgument &operator<<(QDBusArgument &argument, const ISD::Dome::Status &source)
486{
487 argument.beginStructure();
489 argument.endStructure();
490 return argument;
491}
492
493const QDBusArgument &operator>>(const QDBusArgument &argument, ISD::Dome::Status &dest)
494{
495 int a;
496 argument.beginStructure();
497 argument >> a;
498 argument.endStructure();
499 dest = static_cast<ISD::Dome::Status>(a);
500 return argument;
501}
502
503QDBusArgument &operator<<(QDBusArgument &argument, const ISD::Dome::ShutterStatus &source)
504{
505 argument.beginStructure();
507 argument.endStructure();
508 return argument;
509}
510
511const QDBusArgument &operator>>(const QDBusArgument &argument, ISD::Dome::ShutterStatus &dest)
512{
513 int a;
514 argument.beginStructure();
515 argument >> a;
516 argument.endStructure();
517 dest = static_cast<ISD::Dome::ShutterStatus>(a);
518 return argument;
519}
520
static KNotification * event(const QString &eventId, const QString &text=QString(), const QPixmap &pixmap=QPixmap(), const NotificationFlags &flags=CloseOnTimeout, const QString &componentName=QString())
static KStars * Instance()
Definition kstars.h:123
QString i18n(const char *text, const TYPE &arg...)
ISD is a collection of INDI Standard Devices.
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
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-2024 The KDE developers.
Generated on Fri May 17 2024 11:48:26 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.