Kstars

capturedeviceadaptor.cpp
1/* Ekos commands for the capture module
2 SPDX-FileCopyrightText: Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "capturedeviceadaptor.h"
8
9#include "ksmessagebox.h"
10#include "Options.h"
11#include "indi/indistd.h"
12#include "ekos_capture_debug.h"
13#include "sequencejobstate.h"
14
15#include "indi/indicamera.h"
16#include "indi/indidustcap.h"
17#include "indi/indidome.h"
18#include "indi/indilightbox.h"
19#include "indi/indimount.h"
20#include "indi/indirotator.h"
21#include "ekos/auxiliary/rotatorutils.h"
22
23namespace Ekos
24{
25
26
27void CaptureDeviceAdaptor::connectDome(SequenceJobState *state)
28{
29 if (state == nullptr)
30 return;
31
32 connect(state, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
33 connect(this, &CaptureDeviceAdaptor::domeStatusChanged, state, &SequenceJobState::domeStatusChanged);
34}
35
36void CaptureDeviceAdaptor::disconnectDome(SequenceJobState *state)
37{
38 if (state == nullptr)
39 return;
40
41 disconnect(state, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
42 disconnect(this, &CaptureDeviceAdaptor::domeStatusChanged, state, &SequenceJobState::domeStatusChanged);
43}
44
45void CaptureDeviceAdaptor::setCurrentSequenceJobState(QSharedPointer<SequenceJobState> jobState)
46{
47 // clear old connections
48 disconnectDevices(currentSequenceJobState.data());
49 // add new connections
50 connectRotator(jobState.data());
51 connectFilterManager(jobState.data());
52 connectActiveCamera(jobState.data());
53 connectMount(jobState.data());
54 connectDome(jobState.data());
55 connectDustCap(jobState.data());
56 currentSequenceJobState = jobState;
57
58}
59
60void CaptureDeviceAdaptor::setDustCap(ISD::DustCap *device)
61{
62 disconnectDustCap(currentSequenceJobState.data());
63 m_ActiveDustCap = device;
64 connectDustCap(currentSequenceJobState.data());
65}
66
67void CaptureDeviceAdaptor::disconnectDevices(SequenceJobState *state)
68{
69 disconnectRotator(state);
70 disconnectFilterManager(state);
71 disconnectActiveCamera(state);
72 disconnectMount(state);
73 disconnectDome(state);
74 disconnectDustCap(state);
75}
76
77
78
79
80
81void CaptureDeviceAdaptor::connectDustCap(SequenceJobState *state)
82{
83 if (m_ActiveDustCap != nullptr)
84 connect(m_ActiveDustCap, &ISD::DustCap::newStatus, this, &CaptureDeviceAdaptor::dustCapStatusChanged);
85
86 if (state == nullptr)
87 return;
88
89 connect(state, &SequenceJobState::askManualScopeCover, this, &CaptureDeviceAdaptor::askManualScopeCover);
90 connect(state, &SequenceJobState::askManualScopeOpen, this, &CaptureDeviceAdaptor::askManualScopeOpen);
91 connect(state, &SequenceJobState::setLightBoxLight, this, &CaptureDeviceAdaptor::setLightBoxLight);
92 connect(state, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
93
94 connect(this, &CaptureDeviceAdaptor::manualScopeCoverUpdated, state, &SequenceJobState::updateManualScopeCover);
95 connect(this, &CaptureDeviceAdaptor::lightBoxLight, state, &SequenceJobState::lightBoxLight);
96 connect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, state, &SequenceJobState::dustCapStateChanged);
97}
98
99void CaptureDeviceAdaptor::disconnectDustCap(SequenceJobState *state)
100{
101 if (m_ActiveDustCap != nullptr)
102 disconnect(m_ActiveDustCap, nullptr, this, nullptr);
103
104 if (state == nullptr)
105 return;
106
107 disconnect(state, &SequenceJobState::askManualScopeCover, this, &CaptureDeviceAdaptor::askManualScopeCover);
108 disconnect(state, &SequenceJobState::askManualScopeOpen, this, &CaptureDeviceAdaptor::askManualScopeOpen);
109 disconnect(state, &SequenceJobState::setLightBoxLight, this, &CaptureDeviceAdaptor::setLightBoxLight);
110 disconnect(state, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
111
112 disconnect(this, &CaptureDeviceAdaptor::manualScopeCoverUpdated, state, &SequenceJobState::updateManualScopeCover);
113 disconnect(this, &CaptureDeviceAdaptor::lightBoxLight, state, &SequenceJobState::lightBoxLight);
114 disconnect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, state, &SequenceJobState::dustCapStateChanged);
115}
116
117void CaptureDeviceAdaptor::setMount(ISD::Mount *device)
118{
119 if (m_ActiveMount == device)
120 return;
121
122 // clean up old connections
123 if (m_ActiveMount != nullptr)
124 {
125 disconnect(m_ActiveMount, nullptr, this, nullptr);
126 disconnectMount(currentSequenceJobState.data());
127 }
128 // connect new device
129 if (device != nullptr)
130 {
131 connect(device, &ISD::Mount::newStatus, this, &CaptureDeviceAdaptor::scopeStatusChanged);
132 connect(device, &ISD::Mount::pierSideChanged, this, &CaptureDeviceAdaptor::pierSideChanged);
133 connect(device, &ISD::Mount::newParkStatus, this, &CaptureDeviceAdaptor::scopeParkStatusChanged);
134 connectMount(currentSequenceJobState.data());
135
136 // update mount states
137 emit pierSideChanged(device->pierSide());
138 emit scopeParkStatusChanged(device->parkStatus());
139 }
140
141 m_ActiveMount = device;
142}
143
144void CaptureDeviceAdaptor::connectMount(SequenceJobState *state)
145{
146 if (state == nullptr)
147 return;
148
149 connect(state, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
150 connect(state, &SequenceJobState::setScopeTracking, this, &CaptureDeviceAdaptor::setScopeTracking);
151 connect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
152
153 connect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
154 connect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
155}
156
157void CaptureDeviceAdaptor::disconnectMount(SequenceJobState *state)
158{
159 if (state == nullptr)
160 return;
161
162 disconnect(state, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
163 disconnect(state, &SequenceJobState::setScopeTracking, this, &CaptureDeviceAdaptor::setScopeTracking);
164 disconnect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
165
166 disconnect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
167 disconnect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
168}
169
170void CaptureDeviceAdaptor::setDome(ISD::Dome *device)
171{
172 if (m_ActiveDome == device)
173 return;
174
175 // clean up old connections
176 if (m_ActiveDome != nullptr)
177 {
178 disconnect(m_ActiveDome, nullptr, this, nullptr);
179 disconnectDome(currentSequenceJobState.data());
180 }
181 // connect new device
182 if (device != nullptr)
183 {
184 connect(device, &ISD::Dome::newStatus, this, &CaptureDeviceAdaptor::domeStatusChanged);
185 connectDome(currentSequenceJobState.data());
186 }
187
188 m_ActiveDome = device;
189}
190
191void CaptureDeviceAdaptor::setRotator(ISD::Rotator *device)
192{
193 // do nothing if *real* rotator is already connected
194 if ((m_ActiveRotator == device) && (device != nullptr))
195 return;
196
197 // clean up old connections
198 if (m_ActiveRotator != nullptr)
199 {
200 m_ActiveRotator->disconnect(this);
201 disconnectRotator(currentSequenceJobState.data());
202 }
203
204 m_ActiveRotator = device;
205
206 // connect new device
207 if (m_ActiveRotator != nullptr)
208 {
209 connect(m_ActiveRotator, &ISD::Rotator::newAbsoluteAngle, this, &CaptureDeviceAdaptor::newRotatorAngle,
211 connect(m_ActiveRotator, &ISD::Rotator::reverseToggled, this, &CaptureDeviceAdaptor::rotatorReverseToggled,
213 connectRotator(currentSequenceJobState.data());
214
215 emit newRotator(device->getDeviceName());
216 }
217 else
218 emit newRotator(""); // no real rotator present, so check if user wants to use "manual rotator"
219
220}
221
222void CaptureDeviceAdaptor::connectRotator(SequenceJobState *state)
223{
224 if (state == nullptr)
225 return;
226
227 connect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle,
229 connect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
230}
231
232void CaptureDeviceAdaptor::disconnectRotator(SequenceJobState *state)
233{
234 if (state == nullptr)
235 return;
236
237 disconnect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
238 disconnect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle);
239}
240
241void CaptureDeviceAdaptor::setRotatorAngle(double rawAngle)
242{
243 if (m_ActiveRotator != nullptr && m_ActiveRotator->setAbsoluteAngle(rawAngle))
244 {
245 RotatorUtils::Instance()->initTimeFrame(rawAngle);
246 qCInfo(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to" << rawAngle << "degrees.";
247 }
248 else
249 qCWarning(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to " << rawAngle
250 << "failed due to missing or unresponsive rotator.";
251}
252
253double CaptureDeviceAdaptor::getRotatorAngle()
254{
255 if (m_ActiveRotator != nullptr)
256 return m_ActiveRotator->absoluteAngle();
257 else
258 return 0;
259}
260
261IPState CaptureDeviceAdaptor::getRotatorAngleState()
262{
263 if (m_ActiveRotator != nullptr)
264 return m_ActiveRotator->absoluteAngleState();
265 else
266 return IPS_ALERT;
267}
268
269void CaptureDeviceAdaptor::reverseRotator(bool toggled)
270{
271 if (m_ActiveRotator != nullptr)
272 {
273 m_ActiveRotator->setReversed(toggled);
274 m_ActiveRotator->setConfig(SAVE_CONFIG);
275 }
276}
277
278void CaptureDeviceAdaptor::readRotatorAngle()
279{
280 if (m_ActiveRotator != nullptr)
281 emit newRotatorAngle(m_ActiveRotator->absoluteAngle(), m_ActiveRotator->absoluteAngleState());
282}
283
284
285
286void CaptureDeviceAdaptor::setActiveCamera(ISD::Camera *device)
287{
288 if (m_ActiveCamera == device)
289 return;
290
291 // disconnect device events if the new device is not empty
292 if (m_ActiveCamera != nullptr)
293 {
294 m_ActiveCamera->disconnect(this);
295 disconnectActiveCamera(currentSequenceJobState.data());
296
297 }
298
299 // store the link to the new device
300 m_ActiveCamera = device;
301
302 // connect device events if the new device is not empty
303 if (m_ActiveCamera != nullptr)
304 {
305 // publish device events
306 connect(m_ActiveCamera, &ISD::Camera::newTemperatureValue, this,
307 &CaptureDeviceAdaptor::newCCDTemperatureValue, Qt::UniqueConnection);
308 connect(m_ActiveCamera, &ISD::ConcreteDevice::Connected, this, [this]()
309 {
310 emit CameraConnected(true);
311 });
312 connect(m_ActiveCamera, &ISD::ConcreteDevice::Disconnected, this, [this]()
313 {
314 emit CameraConnected(false);
315 });
316
317 if (m_ActiveCamera->hasGuideHead())
318 addGuideHead(device);
319 }
320 connectActiveCamera(currentSequenceJobState.data());
321
322 // communicate new camera
323 emit newCamera(device == nullptr ? "" : device->getDeviceName());
324}
325
326void CaptureDeviceAdaptor::setFilterWheel(ISD::FilterWheel *device)
327{
328 if (m_ActiveFilterWheel == device)
329 return;
330
331 // disconnect device events if the new device is not empty
332 if (m_ActiveFilterWheel != nullptr)
333 m_ActiveFilterWheel->disconnect(this);
334
335 // store the link to the new device
336 m_ActiveFilterWheel = device;
337
338 // connect device events if the new device is not empty
339 if (m_ActiveFilterWheel != nullptr)
340 {
341 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Connected, this, [this]()
342 {
343 emit FilterWheelConnected(true);
344 });
345 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Disconnected, this, [this]()
346 {
347 emit FilterWheelConnected(false);
348 });
349 }
350
351 // communicate new device
352 emit newFilterWheel(device == nullptr ? "" : device->getDeviceName());
353}
354
355void CaptureDeviceAdaptor::connectActiveCamera(SequenceJobState *state)
356{
357 if (state == nullptr)
358 return;
359
360 //connect state machine to device adaptor
361 connect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
362 connect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
363 connect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
364
365 // forward own events to the state machine
366 connect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
367 connect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
368 connect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature,
370}
371
372void CaptureDeviceAdaptor::disconnectActiveCamera(SequenceJobState *state)
373{
374 if (state == nullptr)
375 return;
376
377 disconnect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
378 disconnect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
379 disconnect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
380
381 disconnect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
382 disconnect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
383 disconnect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature);
384}
385
386void CaptureDeviceAdaptor::connectFilterManager(SequenceJobState *state)
387{
388 if (state == nullptr)
389 return;
390
391 connect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
392 connect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
393 connect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID);
394
395 if (m_FilterManager.isNull() == false)
396 connect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
397}
398
399void CaptureDeviceAdaptor::disconnectFilterManager(SequenceJobState *state)
400{
401 if (state == nullptr)
402 return;
403
404 disconnect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
405 disconnect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
406 disconnect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID);
407
408 if (m_FilterManager.isNull() == false)
409 disconnect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
410}
411
412void Ekos::CaptureDeviceAdaptor::updateFilterPosition()
413{
414 if (m_FilterManager.isNull())
415 {
416 qCritical(KSTARS_EKOS_CAPTURE) << "Filter manager is not initilized yet. Filter wheel missing from train?";
417 emit filterIdChanged(-1);
418 }
419 else
420 emit filterIdChanged(m_FilterManager->getFilterPosition());
421}
422
423void CaptureDeviceAdaptor::readCurrentState(CaptureState state)
424{
425 switch(state)
426 {
428 if (m_ActiveCamera != nullptr)
429 {
430 double currentTemperature;
431 m_ActiveCamera->getTemperature(&currentTemperature);
432 emit newCCDTemperatureValue(currentTemperature);
433 }
434 break;
436 readRotatorAngle();
437 break;
439 // intentionally left empty since the guider regularly updates the drift
440 break;
441 default:
442 // this should not happen!
443 qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
444 break;
445 }
446}
447
448void CaptureDeviceAdaptor::setCCDTemperature(double temp)
449{
450 if (m_ActiveCamera != nullptr)
451 m_ActiveCamera->setTemperature(temp);
452}
453
454void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
455{
456 if (m_ActiveChip != nullptr)
457 m_ActiveChip->setBatchMode(enable);
458}
459
460void CaptureDeviceAdaptor::abortFastExposure()
461{
462 if (m_ActiveCamera != nullptr && m_ActiveChip != nullptr && m_ActiveCamera->isFastExposureEnabled())
463 m_ActiveChip->abortExposure();
464}
465
466double CaptureDeviceAdaptor::cameraGain(QMap<QString, QMap<QString, QVariant> > propertyMap)
467{
468 if (getActiveCamera())
469 {
470 // derive attributes from active camera
471 if (getActiveCamera()->getProperty("CCD_GAIN"))
472 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
473 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
474 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
475 }
476 else // no active camera set, e.g. whien used from the scheduler
477 {
478 // if camera is unknown, use the custom property that is set
479 if (propertyMap.keys().contains("CCD_GAIN"))
480 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
481 else if(propertyMap.keys().contains("CCD_CONTROLS"))
482 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
483 }
484
485 // none found
486 return -1;
487
488}
489
490double CaptureDeviceAdaptor::cameraGain()
491{
492 double value = INVALID_VALUE;
493 if (getActiveCamera() != nullptr)
494 getActiveCamera()->getGain(&value);
495
496 return value;
497}
498
499double CaptureDeviceAdaptor::cameraOffset(QMap<QString, QMap<QString, QVariant> > propertyMap)
500{
501 if (getActiveCamera())
502 {
503 if (getActiveCamera()->getProperty("CCD_OFFSET"))
504 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
505 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
506 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
507 }
508 else
509 {
510 // if camera is unknown, use the custom property that is set
511 if (propertyMap.keys().contains("CCD_OFFSET"))
512 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
513 else if(propertyMap.keys().contains("CCD_CONTROLS"))
514 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
515 }
516 return -1;
517}
518
519double CaptureDeviceAdaptor::cameraOffset()
520{
521 double value = INVALID_VALUE;
522 if (getActiveCamera() != nullptr)
523 getActiveCamera()->getOffset(&value);
524
525 return value;
526}
527
528double CaptureDeviceAdaptor::cameraTemperature()
529{
530 double value = INVALID_VALUE;
531 if (getActiveCamera() != nullptr)
532 getActiveCamera()->getTemperature(&value);
533
534 return value;
535}
536
537void CaptureDeviceAdaptor::setFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy)
538{
539 if (m_FilterManager.isNull() == false && m_ActiveFilterWheel != nullptr)
540 m_FilterManager->setFilterPosition(targetFilterPosition, policy);
541}
542
543
544
545
546
547void CaptureDeviceAdaptor::setFilterManager(QSharedPointer<FilterManager> device)
548{
549 // avoid doubled definition
550 if (m_FilterManager == device)
551 return;
552
553 // disconnect old filter manager
554 if (m_FilterManager.isNull() == false)
555 {
556 disconnect(m_FilterManager.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
557 disconnectFilterManager(currentSequenceJobState.data());
558 }
559 //connect new filter manager
560 if (device.isNull() == false)
561 {
562 connect(device.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
563 connectFilterManager(currentSequenceJobState.data());
564 }
565
566 m_FilterManager = device;
567}
568
569void CaptureDeviceAdaptor::askManualScopeCover(QString question, QString title, bool light)
570{
571 // do not ask again
572 if (light && m_ManualLightCoveringAsked == true)
573 {
574 emit manualScopeCoverUpdated(true, true, true);
575 return;
576 }
577 else if (!light && m_ManualDarkCoveringAsked == true)
578 {
579 emit manualScopeCoverUpdated(true, true, false);
580 return;
581 }
582
583 // Continue
584 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
585 {
586 emit manualScopeCoverUpdated(true, true, light);
587 KSMessageBox::Instance()->disconnect(this);
588 m_ManualLightCoveringAsked = false;
589 m_ManualLightOpeningAsked = false;
590 m_ManualDarkCoveringAsked = false;
591 m_ManualDarkOpeningAsked = false;
592 if (light)
593 m_ManualLightCoveringAsked = true;
594 else
595 m_ManualDarkCoveringAsked = true;
596 });
597
598 // Cancel
599 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
600 {
601 if (light)
602 m_ManualLightCoveringAsked = false;
603 else
604 m_ManualDarkCoveringAsked = false;
605
606 emit manualScopeCoverUpdated(true, false, light);
607 KSMessageBox::Instance()->disconnect(this);
608 });
609
610 KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
611
612}
613
614void CaptureDeviceAdaptor::askManualScopeOpen(bool light)
615{
616 // do not ask again
617 if (light && m_ManualLightOpeningAsked == true)
618 {
619 emit manualScopeCoverUpdated(false, true, true);
620 return;
621 }
622 else if (!light && m_ManualDarkOpeningAsked == true)
623 {
624 emit manualScopeCoverUpdated(false, true, false);
625 return;
626 }
627
628 // Continue
629 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
630 {
631 m_ManualLightCoveringAsked = false;
632 m_ManualLightOpeningAsked = false;
633 m_ManualDarkCoveringAsked = false;
634 m_ManualDarkOpeningAsked = false;
635
636 if (light)
637 m_ManualLightOpeningAsked = true;
638 else
639 m_ManualDarkOpeningAsked = true;
640
641 emit manualScopeCoverUpdated(false, true, light);
642 KSMessageBox::Instance()->disconnect(this);
643 });
644
645 // Cancel
646 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
647 {
648 if (light)
649 m_ManualLightOpeningAsked = false;
650 else
651 m_ManualDarkOpeningAsked = false;
652 emit manualScopeCoverUpdated(false, false, light);
653 KSMessageBox::Instance()->disconnect(this);
654 });
655
656 KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
657 i18n("Telescope Covered"), Options::manualCoverTimeout());
658
659}
660
661void CaptureDeviceAdaptor::setLightBoxLight(bool on)
662{
663 m_ActiveLightBox->setLightEnabled(on);
664 emit lightBoxLight(on);
665}
666
667void CaptureDeviceAdaptor::parkDustCap(bool park)
668{
669 // park
670 if (park == true)
671 if (m_ActiveDustCap->park())
672 emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
673 else
674 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
675 // unpark
676 else if (m_ActiveDustCap->unpark())
677 emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
678 else
679 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
680}
681
682void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
683{
684 if (m_ActiveMount != nullptr)
685 {
686 m_ActiveMount->Slew(&target);
687 emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
688 }
689}
690
691void CaptureDeviceAdaptor::setScopeTracking(bool on)
692{
693 if (m_ActiveMount != nullptr)
694 {
695 m_ActiveMount->setTrackEnabled(on);
696 emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
697 }
698}
699
700void CaptureDeviceAdaptor::setScopeParked(bool parked)
701{
702 if (m_ActiveMount != nullptr)
703 {
704 if (parked == true)
705 {
706 if (m_ActiveMount->park())
707 emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
708 else
709 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
710 }
711 else
712 {
713 if (m_ActiveMount->unpark() == false)
714 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
715 }
716 }
717}
718
719void CaptureDeviceAdaptor::setDomeParked(bool parked)
720{
721 if (m_ActiveDome != nullptr)
722 {
723 if (parked == true)
724 {
725 if (m_ActiveDome->park())
726 emit domeStatusChanged(ISD::Dome::DOME_PARKING);
727 else
728 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
729 }
730 else
731 {
732 if (m_ActiveDome->unpark() == false)
733 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
734 }
735 }
736
737}
738
739void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
740{
741 if (getFilterManager()->syncAbsoluteFocusPosition(targetFilterID - 1))
742 emit flatSyncFocusChanged(true);
743 else
744 emit flatSyncFocusChanged(false);
745}
746
747void CaptureDeviceAdaptor::queryHasShutter()
748{
749 if (m_ActiveCamera == nullptr)
750 {
751 emit hasShutter(false);
752 return;
753 }
754 QStringList shutterfulCCDs = Options::shutterfulCCDs();
755 QStringList shutterlessCCDs = Options::shutterlessCCDs();
756 QString deviceName = m_ActiveCamera->getDeviceName();
757
758 bool shutterFound = shutterfulCCDs.contains(deviceName);
759 // FIXME: what about || (captureISOS && captureISOS->count() > 0?
760 bool noShutterFound = shutterlessCCDs.contains(deviceName);
761
762 if (shutterFound == true)
763 emit hasShutter(true);
764 else if (noShutterFound == true)
765 emit hasShutter(false);
766 else
767 {
768 // If we have no information, we ask before we proceed.
769 QString deviceName = m_ActiveCamera->getDeviceName();
770 // Yes, has shutter
771 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
772 {
773 KSMessageBox::Instance()->disconnect(this);
774 QStringList shutterfulCCDs = Options::shutterfulCCDs();
775 shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
776 Options::setShutterfulCCDs(shutterfulCCDs);
777 emit hasShutter(true);
778 });
779 // No, has no shutter
780 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
781 {
782 KSMessageBox::Instance()->disconnect(this);
783 QStringList shutterlessCCDs = Options::shutterlessCCDs();
784 shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
785 Options::setShutterlessCCDs(shutterlessCCDs);
786 emit hasShutter(false);
787 });
788
789 KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
790 i18n("Dark Exposure"));
791 }
792}
793
794} // namespace
Camera class controls an INDI Camera device.
Definition indicamera.h:47
Class handles control of INDI dome devices.
Definition indidome.h:23
Handles operation of a remotely controlled dust cover cap.
Definition indidustcap.h:23
Q_SCRIPTABLE bool unpark()
UnPark Open dust cap.
Q_SCRIPTABLE bool park()
Park Close dust cap.
Q_SCRIPTABLE bool setLightEnabled(bool enable)
SetLightEnabled Turn on/off light.
device handle controlling Mounts.
Definition indimount.h:27
void newStatus(ISD::Mount::Status status)
Change in the mount status.
Rotator class handles control of INDI Rotator devices.
Definition indirotator.h:20
The sky coordinates of a point in the sky.
Definition skypoint.h:45
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:78
@ CAPTURE_GUIDER_DRIFT
Definition ekos.h:106
@ CAPTURE_SETTING_ROTATOR
Definition ekos.h:108
@ CAPTURE_SETTING_TEMPERATURE
Definition ekos.h:107
ISD is a collection of INDI Standard Devices.
QCA_EXPORT QVariant getProperty(const QString &name)
void accepted()
void rejected()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
T * data() const const
T * get() const const
bool isNull() const const
UniqueConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.