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 CaptureDeviceAdaptor::readCurrentState(CaptureState state)
425{
426 switch(state)
427 {
429 if (m_ActiveCamera != nullptr)
430 {
431 double currentTemperature;
432 m_ActiveCamera->getTemperature(&currentTemperature);
433 emit newCCDTemperatureValue(currentTemperature);
434 }
435 break;
437 readRotatorAngle();
438 break;
440 // intentionally left empty since the guider regularly updates the drift
441 break;
442 default:
443 // this should not happen!
444 qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
445 break;
446 }
447}
448
449void CaptureDeviceAdaptor::readCurrentMountParkState()
450{
451 if (m_ActiveMount != nullptr)
452 emit scopeParkStatusChanged(m_ActiveMount->parkStatus());
453}
454
455void CaptureDeviceAdaptor::setCCDTemperature(double temp)
456{
457 if (m_ActiveCamera != nullptr)
458 m_ActiveCamera->setTemperature(temp);
459}
460
461void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
462{
463 if (m_ActiveChip != nullptr)
464 m_ActiveChip->setBatchMode(enable);
465}
466
467void CaptureDeviceAdaptor::abortFastExposure()
468{
469 if (m_ActiveCamera != nullptr && m_ActiveChip != nullptr && m_ActiveCamera->isFastExposureEnabled())
470 m_ActiveChip->abortExposure();
471}
472
473double CaptureDeviceAdaptor::cameraGain(QMap<QString, QMap<QString, QVariant> > propertyMap)
474{
475 if (getActiveCamera())
476 {
477 // derive attributes from active camera
478 if (getActiveCamera()->getProperty("CCD_GAIN"))
479 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
480 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
481 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
482 }
483 else // no active camera set, e.g. whien used from the scheduler
484 {
485 // if camera is unknown, use the custom property that is set
486 if (propertyMap.keys().contains("CCD_GAIN"))
487 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
488 else if(propertyMap.keys().contains("CCD_CONTROLS"))
489 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
490 }
491
492 // none found
493 return -1;
494
495}
496
497double CaptureDeviceAdaptor::cameraGain()
498{
499 double value = INVALID_VALUE;
500 if (getActiveCamera() != nullptr)
501 getActiveCamera()->getGain(&value);
502
503 return value;
504}
505
506double CaptureDeviceAdaptor::cameraOffset(QMap<QString, QMap<QString, QVariant> > propertyMap)
507{
508 if (getActiveCamera())
509 {
510 if (getActiveCamera()->getProperty("CCD_OFFSET"))
511 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
512 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
513 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
514 }
515 else
516 {
517 // if camera is unknown, use the custom property that is set
518 if (propertyMap.keys().contains("CCD_OFFSET"))
519 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
520 else if(propertyMap.keys().contains("CCD_CONTROLS"))
521 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
522 }
523 return -1;
524}
525
526double CaptureDeviceAdaptor::cameraOffset()
527{
528 double value = INVALID_VALUE;
529 if (getActiveCamera() != nullptr)
530 getActiveCamera()->getOffset(&value);
531
532 return value;
533}
534
535double CaptureDeviceAdaptor::cameraTemperature()
536{
537 double value = INVALID_VALUE;
538 if (getActiveCamera() != nullptr)
539 getActiveCamera()->getTemperature(&value);
540
541 return value;
542}
543
544void CaptureDeviceAdaptor::setFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy)
545{
546 if (m_FilterManager.isNull() == false && m_ActiveFilterWheel != nullptr)
547 m_FilterManager->setFilterPosition(targetFilterPosition, policy);
548}
549
550
551
552
553
554void CaptureDeviceAdaptor::setFilterManager(QSharedPointer<FilterManager> device)
555{
556 // avoid doubled definition
557 if (m_FilterManager == device)
558 return;
559
560 // disconnect old filter manager
561 if (m_FilterManager.isNull() == false)
562 {
563 disconnect(m_FilterManager.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
564 disconnectFilterManager(currentSequenceJobState.data());
565 }
566 //connect new filter manager
567 if (device.isNull() == false)
568 {
569 connect(device.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
570 connectFilterManager(currentSequenceJobState.data());
571 }
572
573 m_FilterManager = device;
574}
575
576void CaptureDeviceAdaptor::askManualScopeCover(QString question, QString title, bool light)
577{
578 // do not ask again
579 if (light && m_ManualLightCoveringAsked == true)
580 {
581 emit manualScopeCoverUpdated(true, true, true);
582 return;
583 }
584 else if (!light && m_ManualDarkCoveringAsked == true)
585 {
586 emit manualScopeCoverUpdated(true, true, false);
587 return;
588 }
589
590 // Continue
591 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
592 {
593 emit manualScopeCoverUpdated(true, true, light);
594 KSMessageBox::Instance()->disconnect(this);
595 m_ManualLightCoveringAsked = false;
596 m_ManualLightOpeningAsked = false;
597 m_ManualDarkCoveringAsked = false;
598 m_ManualDarkOpeningAsked = false;
599 if (light)
600 m_ManualLightCoveringAsked = true;
601 else
602 m_ManualDarkCoveringAsked = true;
603 });
604
605 // Cancel
606 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
607 {
608 if (light)
609 m_ManualLightCoveringAsked = false;
610 else
611 m_ManualDarkCoveringAsked = false;
612
613 emit manualScopeCoverUpdated(true, false, light);
614 KSMessageBox::Instance()->disconnect(this);
615 });
616
617 KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
618
619}
620
621void CaptureDeviceAdaptor::askManualScopeOpen(bool light)
622{
623 // do not ask again
624 if (light && m_ManualLightOpeningAsked == true)
625 {
626 emit manualScopeCoverUpdated(false, true, true);
627 return;
628 }
629 else if (!light && m_ManualDarkOpeningAsked == true)
630 {
631 emit manualScopeCoverUpdated(false, true, false);
632 return;
633 }
634
635 // Continue
636 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
637 {
638 m_ManualLightCoveringAsked = false;
639 m_ManualLightOpeningAsked = false;
640 m_ManualDarkCoveringAsked = false;
641 m_ManualDarkOpeningAsked = false;
642
643 if (light)
644 m_ManualLightOpeningAsked = true;
645 else
646 m_ManualDarkOpeningAsked = true;
647
648 emit manualScopeCoverUpdated(false, true, light);
649 KSMessageBox::Instance()->disconnect(this);
650 });
651
652 // Cancel
653 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
654 {
655 if (light)
656 m_ManualLightOpeningAsked = false;
657 else
658 m_ManualDarkOpeningAsked = false;
659 emit manualScopeCoverUpdated(false, false, light);
660 KSMessageBox::Instance()->disconnect(this);
661 });
662
663 KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
664 i18n("Telescope Covered"), Options::manualCoverTimeout());
665
666}
667
668void CaptureDeviceAdaptor::setLightBoxLight(bool on)
669{
670 m_ActiveLightBox->setLightEnabled(on);
671 emit lightBoxLight(on);
672}
673
674void CaptureDeviceAdaptor::parkDustCap(bool park)
675{
676 // park
677 if (park == true)
678 if (m_ActiveDustCap->park())
679 emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
680 else
681 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
682 // unpark
683 else if (m_ActiveDustCap->unpark())
684 emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
685 else
686 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
687}
688
689void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
690{
691 if (m_ActiveMount != nullptr)
692 {
693 m_ActiveMount->Slew(&target);
694 emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
695 }
696}
697
698void CaptureDeviceAdaptor::setScopeTracking(bool on)
699{
700 if (m_ActiveMount != nullptr)
701 {
702 m_ActiveMount->setTrackEnabled(on);
703 emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
704 }
705}
706
707void CaptureDeviceAdaptor::setScopeParked(bool parked)
708{
709 if (m_ActiveMount != nullptr)
710 {
711 if (parked == true)
712 {
713 if (m_ActiveMount->park())
714 emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
715 else
716 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
717 }
718 else
719 {
720 if (m_ActiveMount->unpark() == false)
721 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
722 }
723 }
724}
725
726void CaptureDeviceAdaptor::setDomeParked(bool parked)
727{
728 if (m_ActiveDome != nullptr)
729 {
730 if (parked == true)
731 {
732 if (m_ActiveDome->park())
733 emit domeStatusChanged(ISD::Dome::DOME_PARKING);
734 else
735 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
736 }
737 else
738 {
739 if (m_ActiveDome->unpark() == false)
740 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
741 }
742 }
743
744}
745
746void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
747{
748 if (getFilterManager()->syncAbsoluteFocusPosition(targetFilterID - 1))
749 emit flatSyncFocusChanged(true);
750 else
751 emit flatSyncFocusChanged(false);
752}
753
754void CaptureDeviceAdaptor::queryHasShutter()
755{
756 if (m_ActiveCamera == nullptr)
757 {
758 emit hasShutter(false);
759 return;
760 }
761 QStringList shutterfulCCDs = Options::shutterfulCCDs();
762 QStringList shutterlessCCDs = Options::shutterlessCCDs();
763 QString deviceName = m_ActiveCamera->getDeviceName();
764
765 bool shutterFound = shutterfulCCDs.contains(deviceName);
766 // FIXME: what about || (captureISOS && captureISOS->count() > 0?
767 bool noShutterFound = shutterlessCCDs.contains(deviceName);
768
769 if (shutterFound == true)
770 emit hasShutter(true);
771 else if (noShutterFound == true)
772 emit hasShutter(false);
773 else
774 {
775 // If we have no information, we ask before we proceed.
776 QString deviceName = m_ActiveCamera->getDeviceName();
777 // Yes, has shutter
778 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
779 {
780 KSMessageBox::Instance()->disconnect(this);
781 QStringList shutterfulCCDs = Options::shutterfulCCDs();
782 shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
783 Options::setShutterfulCCDs(shutterfulCCDs);
784 emit hasShutter(true);
785 });
786 // No, has no shutter
787 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
788 {
789 KSMessageBox::Instance()->disconnect(this);
790 QStringList shutterlessCCDs = Options::shutterlessCCDs();
791 shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
792 Options::setShutterlessCCDs(shutterlessCCDs);
793 emit hasShutter(false);
794 });
795
796 KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
797 i18n("Dark Exposure"));
798 }
799}
800
801} // namespace
Camera class controls an INDI Camera device.
Definition indicamera.h:44
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:79
@ 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()
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 Fri Jul 26 2024 11:59:51 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.