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::readCurrentMountParkState, this, &CaptureDeviceAdaptor::readCurrentMountParkState);
152 connect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
153
154 connect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
155 connect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
156}
157
158void CaptureDeviceAdaptor::disconnectMount(SequenceJobState *state)
159{
160 if (state == nullptr)
161 return;
162
163 disconnect(state, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
164 disconnect(state, &SequenceJobState::setScopeTracking, this, &CaptureDeviceAdaptor::setScopeTracking);
165 disconnect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
166
167 disconnect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
168 disconnect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
169}
170
171void CaptureDeviceAdaptor::setDome(ISD::Dome *device)
172{
173 if (m_ActiveDome == device)
174 return;
175
176 // clean up old connections
177 if (m_ActiveDome != nullptr)
178 {
179 disconnect(m_ActiveDome, nullptr, this, nullptr);
180 disconnectDome(currentSequenceJobState.data());
181 }
182 // connect new device
183 if (device != nullptr)
184 {
185 connect(device, &ISD::Dome::newStatus, this, &CaptureDeviceAdaptor::domeStatusChanged);
186 connectDome(currentSequenceJobState.data());
187 }
188
189 m_ActiveDome = device;
190}
191
192void CaptureDeviceAdaptor::setRotator(ISD::Rotator *device)
193{
194 // do nothing if *real* rotator is already connected
195 if ((m_ActiveRotator == device) && (device != nullptr))
196 return;
197
198 // clean up old connections
199 if (m_ActiveRotator != nullptr)
200 {
201 m_ActiveRotator->disconnect(this);
202 disconnectRotator(currentSequenceJobState.data());
203 }
204
205 m_ActiveRotator = device;
206
207 // connect new device
208 if (m_ActiveRotator != nullptr)
209 {
210 connect(m_ActiveRotator, &ISD::Rotator::newAbsoluteAngle, this, &CaptureDeviceAdaptor::newRotatorAngle,
212 connect(m_ActiveRotator, &ISD::Rotator::reverseToggled, this, &CaptureDeviceAdaptor::rotatorReverseToggled,
214 connectRotator(currentSequenceJobState.data());
215
216 emit newRotator(device->getDeviceName());
217 }
218 else
219 emit newRotator(""); // no real rotator present, so check if user wants to use "manual rotator"
220
221}
222
223void CaptureDeviceAdaptor::connectRotator(SequenceJobState *state)
224{
225 if (state == nullptr)
226 return;
227
228 connect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle,
230 connect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
231}
232
233void CaptureDeviceAdaptor::disconnectRotator(SequenceJobState *state)
234{
235 if (state == nullptr)
236 return;
237
238 disconnect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
239 disconnect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle);
240}
241
242void CaptureDeviceAdaptor::setRotatorAngle(double rawAngle)
243{
244 if (m_ActiveRotator != nullptr && m_ActiveRotator->setAbsoluteAngle(rawAngle))
245 {
246 RotatorUtils::Instance()->initTimeFrame(rawAngle);
247 qCInfo(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to" << rawAngle << "degrees.";
248 }
249 else
250 qCWarning(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to " << rawAngle
251 << "failed due to missing or unresponsive rotator.";
252}
253
254double CaptureDeviceAdaptor::getRotatorAngle()
255{
256 if (m_ActiveRotator != nullptr)
257 return m_ActiveRotator->absoluteAngle();
258 else
259 return 0;
260}
261
262IPState CaptureDeviceAdaptor::getRotatorAngleState()
263{
264 if (m_ActiveRotator != nullptr)
265 return m_ActiveRotator->absoluteAngleState();
266 else
267 return IPS_ALERT;
268}
269
270void CaptureDeviceAdaptor::reverseRotator(bool toggled)
271{
272 if (m_ActiveRotator != nullptr)
273 {
274 m_ActiveRotator->setReversed(toggled);
275 m_ActiveRotator->setConfig(SAVE_CONFIG);
276 }
277}
278
279void CaptureDeviceAdaptor::readRotatorAngle()
280{
281 if (m_ActiveRotator != nullptr)
282 emit newRotatorAngle(m_ActiveRotator->absoluteAngle(), m_ActiveRotator->absoluteAngleState());
283}
284
285
286
287void CaptureDeviceAdaptor::setActiveCamera(ISD::Camera *device)
288{
289 if (m_ActiveCamera == device)
290 return;
291
292 // disconnect device events if the new device is not empty
293 if (m_ActiveCamera != nullptr)
294 {
295 m_ActiveCamera->disconnect(this);
296 disconnectActiveCamera(currentSequenceJobState.data());
297
298 }
299
300 // store the link to the new device
301 m_ActiveCamera = device;
302
303 // connect device events if the new device is not empty
304 if (m_ActiveCamera != nullptr)
305 {
306 // publish device events
307 connect(m_ActiveCamera, &ISD::Camera::newTemperatureValue, this,
308 &CaptureDeviceAdaptor::newCCDTemperatureValue, Qt::UniqueConnection);
309 connect(m_ActiveCamera, &ISD::ConcreteDevice::Connected, this, [this]()
310 {
311 emit CameraConnected(true);
312 });
313 connect(m_ActiveCamera, &ISD::ConcreteDevice::Disconnected, this, [this]()
314 {
315 emit CameraConnected(false);
316 });
317
318 if (m_ActiveCamera->hasGuideHead())
319 addGuideHead(device);
320 }
321 connectActiveCamera(currentSequenceJobState.data());
322
323 // communicate new camera
324 emit newCamera(device == nullptr ? "" : device->getDeviceName());
325}
326
327void CaptureDeviceAdaptor::setFilterWheel(ISD::FilterWheel *device)
328{
329 if (m_ActiveFilterWheel == device)
330 return;
331
332 // disconnect device events if the new device is not empty
333 if (m_ActiveFilterWheel != nullptr)
334 m_ActiveFilterWheel->disconnect(this);
335
336 // store the link to the new device
337 m_ActiveFilterWheel = device;
338
339 // connect device events if the new device is not empty
340 if (m_ActiveFilterWheel != nullptr)
341 {
342 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Connected, this, [this]()
343 {
344 emit FilterWheelConnected(true);
345 });
346 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Disconnected, this, [this]()
347 {
348 emit FilterWheelConnected(false);
349 });
350 }
351
352 // communicate new device
353 emit newFilterWheel(device == nullptr ? "" : device->getDeviceName());
354}
355
356void CaptureDeviceAdaptor::connectActiveCamera(SequenceJobState *state)
357{
358 if (state == nullptr)
359 return;
360
361 //connect state machine to device adaptor
362 connect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
363 connect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
364 connect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
365
366 // forward own events to the state machine
367 connect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
368 connect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
369 connect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature,
371}
372
373void CaptureDeviceAdaptor::disconnectActiveCamera(SequenceJobState *state)
374{
375 if (state == nullptr)
376 return;
377
378 disconnect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
379 disconnect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
380 disconnect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
381
382 disconnect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
383 disconnect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
384 disconnect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature);
385}
386
387void CaptureDeviceAdaptor::connectFilterManager(SequenceJobState *state)
388{
389 if (state == nullptr)
390 return;
391
392 connect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
393 connect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
394 connect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID);
395
396 if (m_FilterManager.isNull() == false)
397 connect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
398}
399
400void CaptureDeviceAdaptor::disconnectFilterManager(SequenceJobState *state)
401{
402 if (state == nullptr)
403 return;
404
405 disconnect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
406 disconnect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
407 disconnect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID);
408
409 if (m_FilterManager.isNull() == false)
410 disconnect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
411}
412
413void Ekos::CaptureDeviceAdaptor::updateFilterPosition()
414{
415 if (m_FilterManager.isNull())
416 {
417 qCritical(KSTARS_EKOS_CAPTURE) << "Filter manager is not initilized yet. Filter wheel missing from train?";
418 emit filterIdChanged(-1);
419 }
420 else
421 emit filterIdChanged(m_FilterManager->getFilterPosition());
422}
423
424void Ekos::CaptureDeviceAdaptor::setFilterChangeFailed()
425{
426 qWarning(KSTARS_EKOS_CAPTURE) << "Failed to change filter wheel to target position!";
427 emit filterIdChanged(-1);
428}
429
430void CaptureDeviceAdaptor::readCurrentState(CaptureState state)
431{
432 switch(state)
433 {
435 if (m_ActiveCamera != nullptr)
436 {
437 double currentTemperature;
438 m_ActiveCamera->getTemperature(&currentTemperature);
439 emit newCCDTemperatureValue(currentTemperature);
440 }
441 break;
443 readRotatorAngle();
444 break;
446 // intentionally left empty since the guider regularly updates the drift
447 break;
448 default:
449 // this should not happen!
450 qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
451 break;
452 }
453}
454
455void CaptureDeviceAdaptor::readCurrentMountParkState()
456{
457 if (m_ActiveMount != nullptr)
458 emit scopeParkStatusChanged(m_ActiveMount->parkStatus());
459}
460
461void CaptureDeviceAdaptor::setCCDTemperature(double temp)
462{
463 if (m_ActiveCamera != nullptr)
464 m_ActiveCamera->setTemperature(temp);
465}
466
467void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
468{
469 if (m_ActiveChip != nullptr)
470 m_ActiveChip->setBatchMode(enable);
471}
472
473void CaptureDeviceAdaptor::abortFastExposure()
474{
475 if (m_ActiveCamera != nullptr && m_ActiveChip != nullptr && m_ActiveCamera->isFastExposureEnabled())
476 m_ActiveChip->abortExposure();
477}
478
479double CaptureDeviceAdaptor::cameraGain(QMap<QString, QMap<QString, QVariant> > propertyMap)
480{
481 if (getActiveCamera())
482 {
483 // derive attributes from active camera
484 if (getActiveCamera()->getProperty("CCD_GAIN"))
485 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
486 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
487 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
488 }
489 else // no active camera set, e.g. whien used from the scheduler
490 {
491 // if camera is unknown, use the custom property that is set
492 if (propertyMap.keys().contains("CCD_GAIN"))
493 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
494 else if(propertyMap.keys().contains("CCD_CONTROLS"))
495 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
496 }
497
498 // none found
499 return -1;
500
501}
502
503double CaptureDeviceAdaptor::cameraGain()
504{
505 double value = INVALID_VALUE;
506 if (getActiveCamera() != nullptr)
507 getActiveCamera()->getGain(&value);
508
509 return value;
510}
511
512double CaptureDeviceAdaptor::cameraOffset(QMap<QString, QMap<QString, QVariant> > propertyMap)
513{
514 if (getActiveCamera())
515 {
516 if (getActiveCamera()->getProperty("CCD_OFFSET"))
517 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
518 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
519 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
520 }
521 else
522 {
523 // if camera is unknown, use the custom property that is set
524 if (propertyMap.keys().contains("CCD_OFFSET"))
525 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
526 else if(propertyMap.keys().contains("CCD_CONTROLS"))
527 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
528 }
529 return -1;
530}
531
532double CaptureDeviceAdaptor::cameraOffset()
533{
534 double value = INVALID_VALUE;
535 if (getActiveCamera() != nullptr)
536 getActiveCamera()->getOffset(&value);
537
538 return value;
539}
540
541double CaptureDeviceAdaptor::cameraTemperature()
542{
543 double value = INVALID_VALUE;
544 if (getActiveCamera() != nullptr)
545 getActiveCamera()->getTemperature(&value);
546
547 return value;
548}
549
550void CaptureDeviceAdaptor::setFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy)
551{
552 if (m_FilterManager.isNull() == false && m_ActiveFilterWheel != nullptr)
553 m_FilterManager->setFilterPosition(targetFilterPosition, policy);
554}
555
556void CaptureDeviceAdaptor::clearFilterManager()
557{
558 m_FilterManager.clear();
559}
560
561void CaptureDeviceAdaptor::setFilterManager(const QSharedPointer<FilterManager> &device)
562{
563 // avoid doubled definition
564 if (m_FilterManager == device)
565 return;
566
567 // disconnect old filter manager
568 if (m_FilterManager.isNull() == false)
569 {
570 disconnect(m_FilterManager.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
571 disconnectFilterManager(currentSequenceJobState.data());
572 }
573 //connect new filter manager
574 if (device.isNull() == false)
575 {
576 connect(device.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
577 connectFilterManager(currentSequenceJobState.data());
578 }
579
580 m_FilterManager = device;
581}
582
583void CaptureDeviceAdaptor::askManualScopeCover(QString question, QString title, bool light)
584{
585 // do not ask again
586 if (light && m_ManualLightCoveringAsked == true)
587 {
588 emit manualScopeCoverUpdated(true, true, true);
589 return;
590 }
591 else if (!light && m_ManualDarkCoveringAsked == true)
592 {
593 emit manualScopeCoverUpdated(true, true, false);
594 return;
595 }
596
597 // Continue
598 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
599 {
600 emit manualScopeCoverUpdated(true, true, light);
601 KSMessageBox::Instance()->disconnect(this);
602 m_ManualLightCoveringAsked = false;
603 m_ManualLightOpeningAsked = false;
604 m_ManualDarkCoveringAsked = false;
605 m_ManualDarkOpeningAsked = false;
606 if (light)
607 m_ManualLightCoveringAsked = true;
608 else
609 m_ManualDarkCoveringAsked = true;
610 });
611
612 // Cancel
613 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
614 {
615 if (light)
616 m_ManualLightCoveringAsked = false;
617 else
618 m_ManualDarkCoveringAsked = false;
619
620 emit manualScopeCoverUpdated(true, false, light);
621 KSMessageBox::Instance()->disconnect(this);
622 });
623
624 KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
625
626}
627
628void CaptureDeviceAdaptor::askManualScopeOpen(bool light)
629{
630 // do not ask again
631 if (light && m_ManualLightOpeningAsked == true)
632 {
633 emit manualScopeCoverUpdated(false, true, true);
634 return;
635 }
636 else if (!light && m_ManualDarkOpeningAsked == true)
637 {
638 emit manualScopeCoverUpdated(false, true, false);
639 return;
640 }
641
642 // Continue
643 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
644 {
645 m_ManualLightCoveringAsked = false;
646 m_ManualLightOpeningAsked = false;
647 m_ManualDarkCoveringAsked = false;
648 m_ManualDarkOpeningAsked = false;
649
650 if (light)
651 m_ManualLightOpeningAsked = true;
652 else
653 m_ManualDarkOpeningAsked = true;
654
655 emit manualScopeCoverUpdated(false, true, light);
656 KSMessageBox::Instance()->disconnect(this);
657 });
658
659 // Cancel
660 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
661 {
662 if (light)
663 m_ManualLightOpeningAsked = false;
664 else
665 m_ManualDarkOpeningAsked = false;
666 emit manualScopeCoverUpdated(false, false, light);
667 KSMessageBox::Instance()->disconnect(this);
668 });
669
670 KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
671 i18n("Telescope Covered"), Options::manualCoverTimeout());
672
673}
674
675void CaptureDeviceAdaptor::setLightBoxLight(bool on)
676{
677 m_ActiveLightBox->setLightEnabled(on);
678 emit lightBoxLight(on);
679}
680
681void CaptureDeviceAdaptor::parkDustCap(bool park)
682{
683 // park
684 if (park == true)
685 if (m_ActiveDustCap->park())
686 emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
687 else
688 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
689 // unpark
690 else if (m_ActiveDustCap->unpark())
691 emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
692 else
693 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
694}
695
696void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
697{
698 if (m_ActiveMount != nullptr)
699 {
700 m_ActiveMount->Slew(&target);
701 emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
702 }
703}
704
705void CaptureDeviceAdaptor::setScopeTracking(bool on)
706{
707 if (m_ActiveMount != nullptr)
708 {
709 m_ActiveMount->setTrackEnabled(on);
710 emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
711 }
712}
713
714void CaptureDeviceAdaptor::setScopeParked(bool parked)
715{
716 if (m_ActiveMount != nullptr)
717 {
718 if (parked == true)
719 {
720 if (m_ActiveMount->park())
721 emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
722 else
723 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
724 }
725 else
726 {
727 if (m_ActiveMount->unpark() == false)
728 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
729 }
730 }
731}
732
733void CaptureDeviceAdaptor::setDomeParked(bool parked)
734{
735 if (m_ActiveDome != nullptr)
736 {
737 if (parked == true)
738 {
739 if (m_ActiveDome->park())
740 emit domeStatusChanged(ISD::Dome::DOME_PARKING);
741 else
742 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
743 }
744 else
745 {
746 if (m_ActiveDome->unpark() == false)
747 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
748 }
749 }
750
751}
752
753void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
754{
755 if (getFilterManager()->syncAbsoluteFocusPosition(targetFilterID - 1))
756 emit flatSyncFocusChanged(true);
757 else
758 emit flatSyncFocusChanged(false);
759}
760
761void CaptureDeviceAdaptor::queryHasShutter()
762{
763 if (m_ActiveCamera == nullptr)
764 {
765 emit hasShutter(false);
766 return;
767 }
768 QStringList shutterfulCCDs = Options::shutterfulCCDs();
769 QStringList shutterlessCCDs = Options::shutterlessCCDs();
770 QString deviceName = m_ActiveCamera->getDeviceName();
771
772 bool shutterFound = shutterfulCCDs.contains(deviceName);
773 // FIXME: what about || (captureISOS && captureISOS->count() > 0?
774 bool noShutterFound = shutterlessCCDs.contains(deviceName);
775
776 if (shutterFound == true)
777 emit hasShutter(true);
778 else if (noShutterFound == true)
779 emit hasShutter(false);
780 else
781 {
782 // If we have no information, we ask before we proceed.
783 QString deviceName = m_ActiveCamera->getDeviceName();
784 // Yes, has shutter
785 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
786 {
787 KSMessageBox::Instance()->disconnect(this);
788 QStringList shutterfulCCDs = Options::shutterfulCCDs();
789 shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
790 Options::setShutterfulCCDs(shutterfulCCDs);
791 emit hasShutter(true);
792 });
793 // No, has no shutter
794 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
795 {
796 KSMessageBox::Instance()->disconnect(this);
797 QStringList shutterlessCCDs = Options::shutterlessCCDs();
798 shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
799 Options::setShutterlessCCDs(shutterlessCCDs);
800 emit hasShutter(false);
801 });
802
803 KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
804 i18n("Dark Exposure"));
805 }
806}
807
808} // namespace
Camera class controls an INDI Camera device.
Definition indicamera.h:45
Class handles control of INDI dome devices.
Definition indidome.h:25
Handles operation of a remotely controlled dust cover cap.
Definition indidustcap.h:25
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:29
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:83
@ CAPTURE_GUIDER_DRIFT
Definition ekos.h:106
@ CAPTURE_SETTING_ROTATOR
Definition ekos.h:108
@ CAPTURE_SETTING_TEMPERATURE
Definition ekos.h:107
QCA_EXPORT QVariant getProperty(const QString &name)
void accepted()
void rejected()
void append(QList< T > &&value)
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
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
UniqueConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:04:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.