Kstars

capturedeviceadaptor.cpp
1 /* Ekos commands for the capture module
2  SPDX-FileCopyrightText: Wolfgang Reissenberger <[email protected]>
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 
14 namespace Ekos
15 {
16 CaptureDeviceAdaptor::CaptureDeviceAdaptor()
17 {
18 
19 }
20 
21 void CaptureDeviceAdaptor::connectDome()
22 {
23  connect(currentSequenceJobState, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
24  connect(this, &CaptureDeviceAdaptor::domeStatusChanged, currentSequenceJobState,
25  &SequenceJobState::domeStatusChanged);
26 }
27 
28 void CaptureDeviceAdaptor::disconnectDome()
29 {
30  disconnect(currentSequenceJobState, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
31  disconnect(this, &CaptureDeviceAdaptor::domeStatusChanged, currentSequenceJobState,
32  &SequenceJobState::domeStatusChanged);
33 }
34 
35 void CaptureDeviceAdaptor::setCurrentSequenceJobState(SequenceJobState *jobState)
36 {
37  currentSequenceJobState = jobState;
38 }
39 
40 void CaptureDeviceAdaptor::setLightBox(ISD::LightBox *device)
41 {
42  if (m_ActiveLightBox == device)
43  return;
44 
45  m_ActiveLightBox = device;
46  if (currentSequenceJobState != nullptr && !currentSequenceJobState->m_CaptureState.isNull())
47  currentSequenceJobState->m_CaptureState->hasLightBox = (device != nullptr);
48 }
49 
50 void CaptureDeviceAdaptor::setDustCap(ISD::DustCap *device)
51 {
52  m_ActiveDustCap = device;
53 }
54 
55 void CaptureDeviceAdaptor::connectDustCap()
56 {
57  if (m_ActiveDustCap != nullptr)
58  connect(m_ActiveDustCap, &ISD::DustCap::newStatus, this, &CaptureDeviceAdaptor::dustCapStatusChanged);
59 
60  connect(currentSequenceJobState, &SequenceJobState::askManualScopeLightCover, this,
61  &CaptureDeviceAdaptor::askManualScopeLightCover);
62  connect(currentSequenceJobState, &SequenceJobState::askManualScopeLightOpen, this,
63  &CaptureDeviceAdaptor::askManualScopeLightOpen);
64  connect(currentSequenceJobState, &SequenceJobState::setLightBoxLight, this,
65  &CaptureDeviceAdaptor::setLightBoxLight);
66  connect(currentSequenceJobState, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
67 
68  connect(this, &CaptureDeviceAdaptor::manualScopeLightCover, currentSequenceJobState,
69  &SequenceJobState::manualScopeLightCover);
70  connect(this, &CaptureDeviceAdaptor::lightBoxLight, currentSequenceJobState, &SequenceJobState::lightBoxLight);
71  connect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, currentSequenceJobState,
72  &SequenceJobState::dustCapStatusChanged);
73 }
74 
75 void CaptureDeviceAdaptor::disconnectDustCap()
76 {
77  if (m_ActiveDustCap != nullptr)
78  disconnect(m_ActiveDustCap, nullptr, this, nullptr);
79 
80  disconnect(currentSequenceJobState, &SequenceJobState::askManualScopeLightCover, this,
81  &CaptureDeviceAdaptor::askManualScopeLightCover);
82  disconnect(currentSequenceJobState, &SequenceJobState::askManualScopeLightOpen, this,
83  &CaptureDeviceAdaptor::askManualScopeLightOpen);
84  disconnect(currentSequenceJobState, &SequenceJobState::setLightBoxLight, this,
85  &CaptureDeviceAdaptor::setLightBoxLight);
86  disconnect(currentSequenceJobState, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
87 
88  disconnect(this, &CaptureDeviceAdaptor::manualScopeLightCover, currentSequenceJobState,
89  &SequenceJobState::manualScopeLightCover);
90  disconnect(this, &CaptureDeviceAdaptor::lightBoxLight, currentSequenceJobState, &SequenceJobState::lightBoxLight);
91  disconnect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, currentSequenceJobState,
92  &SequenceJobState::dustCapStatusChanged);
93 }
94 
95 void CaptureDeviceAdaptor::setMount(ISD::Mount *device)
96 {
97  if (m_ActiveTelescope == device)
98  return;
99 
100  // clean up old connections
101  if (m_ActiveTelescope != nullptr)
102  disconnect(m_ActiveTelescope, nullptr, this, nullptr);
103  // connect new device
104  if (device != nullptr)
105  {
106  connect(device, &ISD::Mount::newStatus, this, &CaptureDeviceAdaptor::scopeStatusChanged);
107  connect(device, &ISD::Mount::newParkStatus, this, &CaptureDeviceAdaptor::scopeParkStatusChanged);
108  }
109 
110  m_ActiveTelescope = device;
111 }
112 
113 void CaptureDeviceAdaptor::connectTelescope()
114 {
115  connect(currentSequenceJobState, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
116  connect(currentSequenceJobState, &SequenceJobState::setScopeTracking, this,
117  &CaptureDeviceAdaptor::setScopeTracking);
118  connect(currentSequenceJobState, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
119 
120  connect(this, &CaptureDeviceAdaptor::scopeStatusChanged, currentSequenceJobState,
121  &SequenceJobState::scopeStatusChanged);
122  connect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, currentSequenceJobState,
123  &SequenceJobState::scopeParkStatusChanged);
124 }
125 
126 void CaptureDeviceAdaptor::disconnectTelescope()
127 {
128  disconnect(currentSequenceJobState, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
129  disconnect(currentSequenceJobState, &SequenceJobState::setScopeTracking, this,
130  &CaptureDeviceAdaptor::setScopeTracking);
131  disconnect(currentSequenceJobState, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
132 
133  disconnect(this, &CaptureDeviceAdaptor::scopeStatusChanged, currentSequenceJobState,
134  &SequenceJobState::scopeStatusChanged);
135  disconnect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, currentSequenceJobState,
136  &SequenceJobState::scopeParkStatusChanged);
137 }
138 
139 void CaptureDeviceAdaptor::setDome(ISD::Dome *device)
140 {
141  if (m_ActiveDome == device)
142  return;
143 
144  // clean up old connections
145  if (m_ActiveDome != nullptr)
146  disconnect(m_ActiveDome, nullptr, this, nullptr);
147  // connect new device
148  if (device != nullptr)
149  connect(device, &ISD::Dome::newStatus, this, &CaptureDeviceAdaptor::domeStatusChanged);
150 
151  m_ActiveDome = device;
152 }
153 
154 void CaptureDeviceAdaptor::setRotator(ISD::Rotator *device)
155 {
156  if (m_ActiveRotator == device)
157  return;
158 
159  // clean up old connections
160  if (m_ActiveRotator != nullptr)
161  m_ActiveRotator->disconnect(this);
162 
163  m_ActiveRotator = device;
164 
165  // connect new device
166  if (m_ActiveRotator != nullptr)
167  {
168  connect(m_ActiveRotator, &ISD::Rotator::newAbsoluteAngle, this, &CaptureDeviceAdaptor::newRotatorAngle,
170  connect(m_ActiveRotator, &ISD::Rotator::reverseToggled, this, &CaptureDeviceAdaptor::rotatorReverseToggled,
172 
173  emit newRotatorAngle(device->absoluteAngle(), device->absoluteAngleState());
174  emit rotatorReverseToggled(device->isReversed());
175 
176  }
177 }
178 
179 void CaptureDeviceAdaptor::connectRotator()
180 {
181  connect(this, &CaptureDeviceAdaptor::newRotatorAngle, currentSequenceJobState,
182  &SequenceJobState::setCurrentRotatorPositionAngle, Qt::UniqueConnection);
183  connect(currentSequenceJobState, &SequenceJobState::setRotatorAngle, this,
184  &CaptureDeviceAdaptor::setRotatorAngle);
185 }
186 
187 void CaptureDeviceAdaptor::disconnectRotator()
188 {
189  disconnect(currentSequenceJobState, &SequenceJobState::setRotatorAngle, this,
190  &CaptureDeviceAdaptor::setRotatorAngle);
191  disconnect(this, &CaptureDeviceAdaptor::newRotatorAngle, currentSequenceJobState,
192  &SequenceJobState::setCurrentRotatorPositionAngle);
193 }
194 
195 void CaptureDeviceAdaptor::setRotatorAngle(double *rawAngle)
196 {
197  if (m_ActiveRotator != nullptr)
198  m_ActiveRotator->setAbsoluteAngle(*rawAngle);
199 }
200 
201 void CaptureDeviceAdaptor::reverseRotator(bool toggled)
202 {
203  if (m_ActiveRotator != nullptr)
204  {
205  m_ActiveRotator->setReversed(toggled);
206  m_ActiveRotator->setConfig(SAVE_CONFIG);
207  }
208 }
209 
210 void CaptureDeviceAdaptor::readRotatorAngle()
211 {
212  if (m_ActiveRotator != nullptr)
213  emit newRotatorAngle(m_ActiveRotator->absoluteAngle(), m_ActiveRotator->absoluteAngleState());
214 }
215 
216 void CaptureDeviceAdaptor::setActiveCamera(ISD::Camera *device)
217 {
218  if (m_ActiveCamera == device)
219  return;
220 
221  // disconnect device events if the new device is not empty
222  if (m_ActiveCamera != nullptr)
223  {
224  disconnect(m_ActiveCamera, &ISD::Camera::newTemperatureValue, this,
225  &Ekos::CaptureDeviceAdaptor::newCCDTemperatureValue);
226  }
227 
228  // store the link to the new device
229  m_ActiveCamera = device;
230 
231  // connect device events if the new device is not empty
232  if (m_ActiveCamera != nullptr)
233  {
234  // publish device events
235  connect(m_ActiveCamera, &ISD::Camera::newTemperatureValue, this,
236  &Ekos::CaptureDeviceAdaptor::newCCDTemperatureValue, Qt::UniqueConnection);
237  }
238 }
239 
240 void CaptureDeviceAdaptor::connectActiveCamera()
241 {
242  //connect state machine to device adaptor
243  connect(currentSequenceJobState, &SequenceJobState::setCCDTemperature, this,
244  &CaptureDeviceAdaptor::setCCDTemperature);
245  connect(currentSequenceJobState, &SequenceJobState::setCCDBatchMode, this,
246  &CaptureDeviceAdaptor::enableCCDBatchMode);
247  connect(currentSequenceJobState, &SequenceJobState::queryHasShutter, this,
248  &CaptureDeviceAdaptor::queryHasShutter);
249 
250  // forward own events to the state machine
251  connect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, currentSequenceJobState,
252  &SequenceJobState::flatSyncFocusChanged);
253  connect(this, &CaptureDeviceAdaptor::hasShutter, currentSequenceJobState, &SequenceJobState::hasShutter);
254  connect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, currentSequenceJobState,
255  &Ekos::SequenceJobState::setCurrentCCDTemperature, Qt::UniqueConnection);
256 }
257 
258 void CaptureDeviceAdaptor::disconnectActiveCamera()
259 {
260  disconnect(currentSequenceJobState, &SequenceJobState::setCCDTemperature, this,
261  &CaptureDeviceAdaptor::setCCDTemperature);
262  disconnect(currentSequenceJobState, &SequenceJobState::setCCDBatchMode, this,
263  &CaptureDeviceAdaptor::enableCCDBatchMode);
264  disconnect(currentSequenceJobState, &SequenceJobState::queryHasShutter, this,
265  &CaptureDeviceAdaptor::queryHasShutter);
266 
267  disconnect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, currentSequenceJobState,
268  &SequenceJobState::flatSyncFocusChanged);
269  disconnect(this, &CaptureDeviceAdaptor::hasShutter, currentSequenceJobState, &SequenceJobState::hasShutter);
270  disconnect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, currentSequenceJobState,
271  &Ekos::SequenceJobState::setCurrentCCDTemperature);
272 }
273 
274 void CaptureDeviceAdaptor::readCurrentState(Ekos::CaptureState state)
275 {
276  switch(state)
277  {
279  if (m_ActiveCamera != nullptr)
280  {
281  double currentTemperature;
282  m_ActiveCamera->getTemperature(&currentTemperature);
283  emit newCCDTemperatureValue(currentTemperature);
284  }
285  break;
287  readRotatorAngle();
288  break;
290  // intentionally left empty since the guider regularly updates the drift
291  break;
292  default:
293  // this should not happen!
294  qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
295  break;
296  }
297 }
298 
299 void CaptureDeviceAdaptor::setCCDTemperature(double temp)
300 {
301  if (m_ActiveCamera != nullptr)
302  m_ActiveCamera->setTemperature(temp);
303 }
304 
305 void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
306 {
307  if (m_ActiveChip != nullptr)
308  m_ActiveChip->setBatchMode(enable);
309 }
310 
311 void CaptureDeviceAdaptor::setActiveChip(ISD::CameraChip *device)
312 {
313  m_ActiveChip = device;
314 }
315 
316 void CaptureDeviceAdaptor::setFilterWheel(ISD::FilterWheel *device)
317 {
318  m_ActiveFilterWheel = device;
319 }
320 
321 void CaptureDeviceAdaptor::askManualScopeLightCover(QString question, QString title)
322 {
323  // do not ask again
324  if (m_ManualCoveringAsked == true)
325  {
326  emit manualScopeLightCover(true, true);
327  return;
328  }
329 
330  // Continue
331  connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
332  {
333  emit manualScopeLightCover(true, true);
334  KSMessageBox::Instance()->disconnect(this);
335  m_ManualCoveringAsked = true;
336  m_ManualOpeningAsked = false;
337  });
338 
339  // Cancel
340  connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
341  {
342  m_ManualCoveringAsked = false;
343  emit manualScopeLightCover(true, false);
344  KSMessageBox::Instance()->disconnect(this);
345  });
346 
347  KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
348 
349 }
350 
351 void CaptureDeviceAdaptor::askManualScopeLightOpen()
352 {
353  // do not ask again
354  if (m_ManualOpeningAsked == true)
355  {
356  emit manualScopeLightCover(false, true);
357  return;
358  }
359 
360  // Continue
361  connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
362  {
363  m_ManualOpeningAsked = true;
364  m_ManualCoveringAsked = false;
365  emit manualScopeLightCover(false, true);
366  KSMessageBox::Instance()->disconnect(this);
367  });
368 
369  // Cancel
370  connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
371  {
372  m_ManualOpeningAsked = false;
373  emit manualScopeLightCover(false, false);
374  KSMessageBox::Instance()->disconnect(this);
375  });
376 
377  KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
378  i18n("Telescope Covered"), Options::manualCoverTimeout());
379 
380 }
381 
382 void CaptureDeviceAdaptor::setLightBoxLight(bool on)
383 {
384  m_ActiveLightBox->SetLightEnabled(on);
385  emit lightBoxLight(on);
386 }
387 
388 void CaptureDeviceAdaptor::parkDustCap(bool park)
389 {
390  // park
391  if (park == true)
392  if (m_ActiveDustCap->Park())
393  emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
394  else
395  emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
396  // unpark
397  else if (m_ActiveDustCap->UnPark())
398  emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
399  else
400  emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
401 }
402 
403 void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
404 {
405  if (m_ActiveTelescope != nullptr)
406  {
407  m_ActiveTelescope->Slew(&target);
408  emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
409  }
410 }
411 
412 void CaptureDeviceAdaptor::setScopeTracking(bool on)
413 {
414  if (m_ActiveTelescope != nullptr)
415  {
416  m_ActiveTelescope->setTrackEnabled(on);
417  emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
418  }
419 }
420 
421 void Ekos::CaptureDeviceAdaptor::setScopeParked(bool parked)
422 {
423  if (m_ActiveTelescope != nullptr)
424  {
425  if (parked == true)
426  {
427  if (m_ActiveTelescope->park())
428  emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
429  else
430  emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
431  }
432  else
433  {
434  if (m_ActiveTelescope->unPark() == false)
435  emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
436  }
437  }
438 }
439 
440 void Ekos::CaptureDeviceAdaptor::setDomeParked(bool parked)
441 {
442  if (m_ActiveDome != nullptr)
443  {
444  if (parked == true)
445  {
446  if (m_ActiveDome->park())
447  emit domeStatusChanged(ISD::Dome::DOME_PARKING);
448  else
449  emit domeStatusChanged(ISD::Dome::DOME_ERROR);
450  }
451  else
452  {
453  if (m_ActiveDome->unPark() == false)
454  emit domeStatusChanged(ISD::Dome::DOME_ERROR);
455  }
456  }
457 
458 }
459 
460 void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
461 {
462  if (filterManager->syncAbsoluteFocusPosition(targetFilterID - 1))
463  emit flatSyncFocusChanged(true);
464  else
465  emit flatSyncFocusChanged(false);
466 }
467 
468 void CaptureDeviceAdaptor::queryHasShutter()
469 {
470  if (m_ActiveCamera == nullptr)
471  {
472  emit hasShutter(false);
473  return;
474  }
475  QStringList shutterfulCCDs = Options::shutterfulCCDs();
476  QStringList shutterlessCCDs = Options::shutterlessCCDs();
477  QString deviceName = m_ActiveCamera->getDeviceName();
478 
479  bool shutterFound = shutterfulCCDs.contains(deviceName);
480  // FIXME: what about || (captureISOS && captureISOS->count() > 0?
481  bool noShutterFound = shutterlessCCDs.contains(deviceName);
482 
483  if (shutterFound == true)
484  emit hasShutter(true);
485  else if (noShutterFound == true)
486  emit hasShutter(false);
487  else
488  {
489  // If we have no information, we ask before we proceed.
490  QString deviceName = m_ActiveCamera->getDeviceName();
491  // Yes, has shutter
492  connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
493  {
494  KSMessageBox::Instance()->disconnect(this);
495  QStringList shutterfulCCDs = Options::shutterfulCCDs();
496  shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
497  Options::setShutterfulCCDs(shutterfulCCDs);
498  emit hasShutter(true);
499  });
500  // No, has no shutter
501  connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
502  {
503  KSMessageBox::Instance()->disconnect(this);
504  QStringList shutterlessCCDs = Options::shutterlessCCDs();
505  shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
506  Options::setShutterlessCCDs(shutterlessCCDs);
507  emit hasShutter(false);
508  });
509 
510  KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
511  i18n("Dark Exposure"));
512  }
513 }
514 
515 } // namespace
void append(const T &value)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Ekos is an advanced Astrophotography tool for Linux. It is based on a modular extensible framework to...
Definition: align.cpp:66
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
@ CAPTURE_SETTING_ROTATOR
Definition: ekos.h:108
void rejected()
@ CAPTURE_SETTING_TEMPERATURE
Definition: ekos.h:107
QString i18n(const char *text, const TYPE &arg...)
CaptureState
Capture states.
Definition: ekos.h:91
UniqueConnection
void newStatus(ISD::Mount::Status status)
Change in the mount status.
@ CAPTURE_GUIDER_DRIFT
Definition: ekos.h:106
void accepted()
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 19 2022 03:57:49 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.