9#include "analyze/analyze.h"
10#include "capture/capture.h"
11#include "scheduler/scheduler.h"
12#include "scheduler/schedulerprocess.h"
13#include "scheduler/schedulermodulestate.h"
14#include "focus/focus.h"
15#include "align/align.h"
16#include "guide/guide.h"
17#include "mount/mount.h"
18#include "observatory/observatory.h"
21#include "ekosadaptor.h"
23#include "kstarsdata.h"
25#include "ekos/capture/rotatorsettings.h"
26#include "profileeditor.h"
27#include "profilewizard.h"
29#include "auxiliary/darklibrary.h"
30#include "auxiliary/ksmessagebox.h"
31#include "auxiliary/profilesettings.h"
32#include "capture/sequencejob.h"
33#include "capture/cameraprocess.h"
34#include "fitsviewer/fitsview.h"
35#include "fitsviewer/fitsdata.h"
36#include "indi/clientmanager.h"
37#include "indi/driverinfo.h"
38#include "indi/drivermanager.h"
39#include "indi/guimanager.h"
40#include "indi/indilistener.h"
41#include "auxiliary/opticaltrainmanager.h"
42#include "auxiliary/opticaltrainsettings.h"
43#include "indi/indiwebmanager.h"
44#include "indi/indigps.h"
45#include "indi/indiguider.h"
46#include "indi/indirotator.h"
47#include "mount/meridianflipstatuswidget.h"
48#include "ekos/auxiliary/rotatorutils.h"
50#include "ekoslive/ekosliveclient.h"
51#include "ekoslive/message.h"
52#include "ekoslive/media.h"
54#include <basedevice.h>
56#include <KConfigDialog>
58#include <KActionCollection>
59#include <KNotifications/KNotification>
61#include <QFutureWatcher>
64#include <ekos_debug.h>
66#define MAX_REMOTE_INDI_TIMEOUT 15000
67#define MAX_LOCAL_INDI_TIMEOUT 10000
72Manager *Manager::_Manager =
nullptr;
76 if (_Manager ==
nullptr)
77 _Manager =
new Manager(Options::independentWindowEkos() ?
nullptr :
KStars::Instance());
82void Manager::release()
84 ProfileSettings::release();
85 OpticalTrainManager::release();
86 OpticalTrainSettings::release();
87 RotatorUtils::release();
95 if (Options::independentWindowEkos())
104 if (Options::independentWindowEkos())
110 capturePreview->targetLabel->setVisible(
false);
111 capturePreview->mountTarget->setVisible(
false);
114 deviceSplitter->setSizes(
QList<int>({20000, 10000}));
116 qRegisterMetaType<Ekos::CommunicationStatus>(
"Ekos::CommunicationStatus");
117 qDBusRegisterMetaType<Ekos::CommunicationStatus>();
119 new EkosAdaptor(
this);
125 profileModel->setHorizontalHeaderLabels(
QStringList() <<
"id"
130 m_CountdownTimer.setInterval(1000);
133 toolsWidget->setIconSize(
QSize(48, 48));
137 toolsWidget->setTabEnabled(1,
false);
140 toolsWidget->setTabEnabled(2,
false);
145 processINDIB->setToolTip(
i18n(
"Start"));
153 ekosLiveClient.reset(
new EkosLive::Client(
this));
154 connect(ekosLiveClient.get(), &EkosLive::Client::connected,
this, [
this]()
156 emit ekosLiveStatusChanged(true);
158 connect(ekosLiveClient.get(), &EkosLive::Client::disconnected,
this, [
this]()
160 emit ekosLiveStatusChanged(false);
167 ekosLiveClient.get()->show();
168 ekosLiveClient.get()->raise();
171 connect(
this, &Manager::ekosStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setEkosStatingStatus);
172 connect(
this, &Manager::indiStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setINDIStatus);
173 connect(ekosLiveClient.get()->message(), &EkosLive::Message::connected,
this, [&]()
175 ekosLiveB->setIcon(QIcon(
":/icons/cloud-online.svg"));
177 connect(ekosLiveClient.get()->message(), &EkosLive::Message::disconnected,
this, [&]()
179 ekosLiveB->setIcon(QIcon::fromTheme(
"folder-cloud"));
181 connect(ekosLiveClient.get()->media(), &EkosLive::Media::newBoundingRect, ekosLiveClient.get()->message(),
182 &EkosLive::Message::setBoundingRect);
183 connect(ekosLiveClient.get()->message(), &EkosLive::Message::resetPolarView, ekosLiveClient.get()->media(),
184 &EkosLive::Media::resetPolarView);
185 connect(KSMessageBox::Instance(), &KSMessageBox::newMessage, ekosLiveClient.get()->message(),
186 &EkosLive::Message::sendDialog);
189 m_PortSelectorTimer.setInterval(500);
190 m_PortSelectorTimer.setSingleShot(
true);
193 if (m_PortSelector && m_CurrentProfile->portSelector)
195 if (m_PortSelector->shouldShow())
197 m_PortSelector->show();
198 m_PortSelector->raise();
200 ekosLiveClient.get()->message()->requestPortSelection(true);
203 else if (m_CurrentProfile->autoConnect)
204 setPortSelectionComplete();
206 else if (m_CurrentProfile->autoConnect)
207 setPortSelectionComplete();
213 m_PortSelector->show();
214 m_PortSelector->raise();
218 connect(
this, &Ekos::Manager::ekosStatusChanged,
this, [&](Ekos::CommunicationStatus status)
220 indiControlPanelB->setEnabled(status == Ekos::Success);
221 connectB->setEnabled(
false);
222 disconnectB->setEnabled(
false);
223 profileGroup->setEnabled(status == Ekos::Idle || status == Ekos::Error);
224 m_isStarted = (
status == Ekos::Success ||
status == Ekos::Pending);
225 if (status == Ekos::Success)
228 processINDIB->setToolTip(
i18n(
"Stop"));
229 setWindowTitle(
i18nc(
"@title:window",
"Ekos - %1 Profile", m_CurrentProfile->name));
231 else if (status == Ekos::Error || status == Ekos::Idle)
234 processINDIB->setToolTip(
i18n(
"Start"));
239 processINDIB->setToolTip(
i18n(
"Connection in progress. Click to abort."));
272 Options::setProfile(text);
273 if (text ==
"Simulators")
275 editProfileB->setEnabled(
false);
276 deleteProfileB->setEnabled(
false);
280 editProfileB->setEnabled(
true);
281 deleteProfileB->setEnabled(
true);
287 settleTimer.setInterval(1000);
290 if (m_settleStatus != Ekos::Success)
292 m_settleStatus = Ekos::Success;
293 emit settleStatusChanged(m_settleStatus);
329 toolsWidget->tabBar()->setTabIcon(0,
QIcon(
":/icons/ekos_setup.png"));
330 toolsWidget->tabBar()->setTabToolTip(0,
i18n(
"Setup"));
333 schedulerProcess.reset(
new Scheduler());
334 int index = addModuleTab(EkosModule::Scheduler, schedulerModule(),
QIcon(
":/icons/ekos_scheduler.png"));
335 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Scheduler"));
336 capturePreview->shareSchedulerModuleState(schedulerModule()->moduleState());
337 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog,
this, &Ekos::Manager::updateLog);
338 connect(schedulerModule(), &Ekos::Scheduler::newTarget,
this, &Manager::setTarget);
340 connect(schedulerModule(), &Ekos::Scheduler::jobsUpdated, ekosLiveClient.get()->message(),
342 connect(schedulerModule(), &Ekos::Scheduler::settingsUpdated, ekosLiveClient.get()->message(),
344 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog, ekosLiveClient.get()->message(),
347 QJsonObject cStatus =
349 {
"log", schedulerModule()->moduleState()->getLogText()}
352 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
354 connect(schedulerModule(), &Ekos::Scheduler::newStatus, ekosLiveClient.get()->message(),
355 [
this](Ekos::SchedulerState state)
357 QJsonObject cStatus =
362 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
367 connect(analyzeProcess.get(), &Ekos::Analyze::newLog,
this, &Ekos::Manager::updateLog);
369 index = addModuleTab(EkosModule::Analyze, analyzeProcess.get(),
QIcon(
":/icons/ekos_analyze.png"));
370 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Analyze"));
372 numPermanentTabs = index + 1;
380 m_SummaryView.reset(
new SummaryFITSView(capturePreview->previewWidget));
384 m_SummaryView->createFloatingToolBar();
385 m_SummaryView->setCursorMode(FITSView::dragCursor);
386 m_SummaryView->showProcessInfo(
false);
387 capturePreview->setSummaryFITSView(m_SummaryView.get());
390 if (Options::ekosLeftIcons())
396 for (
int i = 0; i < numPermanentTabs; ++i)
398 QIcon icon = toolsWidget->tabIcon(i);
401 toolsWidget->setTabIcon(i, icon);
409 for (
auto &button : qButtons)
410 button->setAutoDefault(false);
413 resize(Options::ekosWindowWidth(), Options::ekosWindowHeight());
430 toolsWidget->disconnect(
this);
447 Options::setEkosWindowWidth(width());
448 Options::setEkosWindowHeight(height());
460 if (profileWizardLaunched ==
false && profiles.count() == 1)
462 profileWizardLaunched =
true;
469 focusManager->updateFocusDetailView();
470 guideManager->updateGuideDetailView();
473void Manager::loadProfiles()
478 profileModel->clear();
480 for (
auto &pi : profiles)
486 profileModel->appendRow(info);
489 profileModel->sort(0);
490 profileCombo->blockSignals(
true);
491 profileCombo->setModel(profileModel.get());
492 profileCombo->setModelColumn(1);
493 profileCombo->blockSignals(
false);
496 int index = profileCombo->findText(Options::profile());
500 profileCombo->setCurrentIndex(index);
503int Manager::addModuleTab(Manager::EkosModule module,
QWidget *tab,
const QIcon &icon)
508 case EkosModule::Observatory:
509 index += guideProcess ? 1 : 0;
510 case EkosModule::Guide:
511 index += alignProcess ? 1 : 0;
512 case EkosModule::Align:
513 index += mountProcess ? 1 : 0;
514 case EkosModule::Mount:
515 index += focusProcess ? 1 : 0;
516 case EkosModule::Focus:
517 index += captureProcess ? 1 : 0;
518 case EkosModule::Capture:
519 index += analyzeProcess ? 1 : 0;
520 case EkosModule::Analyze:
521 index += schedulerProcess ? 1 : 0;
522 case EkosModule::Scheduler:
524 case EkosModule::Setup:
528 index = toolsWidget->count();
532 toolsWidget->insertTab(index, tab, icon,
"");
536void Manager::loadDrivers()
540 if (dv->getDriverSource() != HOST_SOURCE)
541 driversList[dv->getLabel()] = dv;
547 qCDebug(KSTARS_EKOS) <<
"Resetting Ekos Manager...";
549 ProfileSettings::release();
550 OpticalTrainManager::release();
551 OpticalTrainSettings::release();
552 RotatorUtils::release();
554 m_DriverDevicesCount = 0;
558 captureProcess.reset();
559 focusProcess.reset();
560 guideProcess.reset();
561 alignProcess.reset();
562 mountProcess.reset();
563 observatoryProcess.reset();
565 for (
auto &oneManger : m_FilterManagers)
567 m_FilterManagers.clear();
569 for (
auto &oneController : m_RotatorControllers)
570 oneController.
reset();
571 m_RotatorControllers.clear();
573 DarkLibrary::Release();
574 m_PortSelector.reset();
575 m_PortSelectorTimer.stop();
577 Ekos::CommunicationStatus previousStatus;
579 previousStatus = m_settleStatus;
580 m_settleStatus = Ekos::Idle;
581 if (previousStatus != m_settleStatus)
582 emit settleStatusChanged(m_settleStatus);
584 previousStatus = m_ekosStatus;
585 m_ekosStatus = Ekos::Idle;
586 if (previousStatus != m_ekosStatus)
587 emit ekosStatusChanged(m_ekosStatus);
589 previousStatus = m_indiStatus;
590 m_indiStatus = Ekos::Idle;
591 if (previousStatus != m_indiStatus)
592 emit indiStatusChanged(m_indiStatus);
594 connectB->setEnabled(
false);
595 disconnectB->setEnabled(
false);
597 processINDIB->setEnabled(
true);
599 mountGroup->setEnabled(
false);
600 capturePreview->setEnabled(
false);
601 capturePreview->reset();
603 mountStatus->setStyleSheet(
QString());
604 focusManager->reset();
605 guideManager->reset();
610 processINDIB->setToolTip(
i18n(
"Start"));
613void Manager::processINDI()
615 if (m_isStarted ==
false)
624 m_PortSelector.reset();
625 m_PortSelectorTimer.stop();
626 m_CountdownTimer.stop();
627 portSelectorB->setEnabled(
false);
630 indiHubAgent->terminate();
632 profileGroup->setEnabled(
true);
634 setWindowTitle(
i18nc(
"@title:window",
"Ekos"));
639 if (analyzeProcess && Options::analyzeRestartWithEkos())
640 analyzeProcess->restart();
643 if (m_ekosStatus == Ekos::Pending || m_ekosStatus == Ekos::Success)
645 qCWarning(KSTARS_EKOS) <<
"Ekos Manager start called but current Ekos Status is" << m_ekosStatus <<
"Ignoring request.";
649 managedDrivers.clear();
658 getCurrentProfile(m_CurrentProfile);
659 m_LocalMode = m_CurrentProfile->isLocal();
661 ProfileSettings::Instance()->setProfile(m_CurrentProfile);
664 updateProfileLocation(m_CurrentProfile);
666 bool haveCCD =
false, haveGuider =
false;
670 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
672 Options::setPHD2Host(m_CurrentProfile->guiderhost);
673 Options::setPHD2Port(m_CurrentProfile->guiderport);
675 else if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_LINGUIDER)
677 Options::setLinGuiderHost(m_CurrentProfile->guiderhost);
678 Options::setLinGuiderPort(m_CurrentProfile->guiderport);
687 profileScripts = doc.
array();
689 ekosLiveClient->message()->setPendingPropertiesEnabled(
true);
694 auto drv = driversList.value(m_CurrentProfile->mount());
697 managedDrivers.
append(drv->clone());
699 drv = driversList.value(m_CurrentProfile->ccd());
702 managedDrivers.append(drv->clone());
706 Options::setGuiderType(m_CurrentProfile->guidertype);
708 drv = driversList.value(m_CurrentProfile->guider());
719 if (haveCCD && m_CurrentProfile->guider() == m_CurrentProfile->ccd())
721 if (checkUniqueBinaryDriver( driversList.value(m_CurrentProfile->ccd()), drv))
727 drv->setUniqueLabel(drv->getLabel() +
" Guide");
732 managedDrivers.append(drv->clone());
735 drv = driversList.value(m_CurrentProfile->ao());
737 managedDrivers.append(drv->clone());
739 drv = driversList.value(m_CurrentProfile->filter());
741 managedDrivers.append(drv->clone());
743 drv = driversList.value(m_CurrentProfile->focuser());
745 managedDrivers.append(drv->clone());
747 drv = driversList.value(m_CurrentProfile->dome());
749 managedDrivers.append(drv->clone());
751 drv = driversList.value(m_CurrentProfile->weather());
753 managedDrivers.append(drv->clone());
755 drv = driversList.value(m_CurrentProfile->aux1());
758 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
759 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
760 managedDrivers.append(drv->clone());
762 drv = driversList.value(m_CurrentProfile->aux2());
765 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
766 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
767 managedDrivers.append(drv->clone());
770 drv = driversList.value(m_CurrentProfile->aux3());
773 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
774 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
775 managedDrivers.append(drv->clone());
778 drv = driversList.value(m_CurrentProfile->aux4());
781 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
782 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
783 managedDrivers.append(drv->clone());
787 if (m_CurrentProfile->remotedrivers.isEmpty() ==
false && m_CurrentProfile->remotedrivers.contains(
"@"))
789 for (
auto remoteDriver : m_CurrentProfile->remotedrivers.split(
","))
791 QString name,
label, host(
"localhost"), port(
"7624"), hostport(host +
':' + port);
801 QStringList device_location = remoteDriver.split(
'@');
804 if (device_location.
length() > 0)
805 name = device_location[0];
808 if (device_location.
length() > 1)
809 hostport = device_location[1];
825 dv->setRemoteHost(host);
826 dv->setRemotePort(port);
832 dv->setUniqueLabel(label);
833 managedDrivers.
append(dv);
838 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
840 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
841 managedDrivers.clear();
842 m_ekosStatus = Ekos::Error;
843 emit ekosStatusChanged(m_ekosStatus);
847 m_DriverDevicesCount = managedDrivers.count();
853 remote_indi->setHostParameters(m_CurrentProfile->host, m_CurrentProfile->port);
855 remote_indi->setDriverSource(GENERATED_SOURCE);
857 managedDrivers.append(remote_indi);
859 haveCCD = m_CurrentProfile->drivers.contains(
"CCD");
860 haveGuider = m_CurrentProfile->drivers.contains(
"Guider");
862 Options::setGuiderType(m_CurrentProfile->guidertype);
864 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
866 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
867 m_DriverDevicesCount = 0;
868 m_ekosStatus = Ekos::Error;
869 emit ekosStatusChanged(m_ekosStatus);
873 m_DriverDevicesCount = m_CurrentProfile->drivers.count();
879 for (
const auto &oneRule : qAsConst(profileScripts))
881 auto driver = oneRule.toObject()[
"Driver"].toString();
882 auto matchingDriver = std::find_if(managedDrivers.begin(), managedDrivers.end(), [oneRule, driver](
const auto & oneDriver)
885 return oneDriver->getLabel() == driver || (driver.startsWith(
"@") && !oneDriver->getRemoteHost().isEmpty());
888 if (matchingDriver != managedDrivers.end())
890 (*matchingDriver)->setStartupRule(oneRule.toObject());
891 sortedList.
append(*matchingDriver);
899 for (
auto &oneDriver : managedDrivers)
901 if (sortedList.
contains(oneDriver) ==
false)
902 sortedList.
append(oneDriver);
905 managedDrivers = sortedList;
908 connect(DriverManager::Instance(), &DriverManager::serverStarted,
this,
910 connect(DriverManager::Instance(), &DriverManager::serverFailed,
this,
912 connect(DriverManager::Instance(), &DriverManager::clientStarted,
this,
914 connect(DriverManager::Instance(), &DriverManager::clientFailed,
this,
916 connect(DriverManager::Instance(), &DriverManager::clientTerminated,
this,
919 connect(INDIListener::Instance(), &INDIListener::newDevice,
this, &Ekos::Manager::processNewDevice);
924 if (m_LocalMode || m_CurrentProfile->host ==
"localhost")
926 if (isRunning(
"PTPCamera"))
928 if (KMessageBox::Yes ==
929 (KMessageBox::questionYesNo(
nullptr,
930 i18n(
"Ekos detected that PTP Camera is running and may prevent a Canon or Nikon camera from connecting to Ekos. Do you want to quit PTP Camera now?"),
931 i18n(
"PTP Camera"), KStandardGuiItem::yes(), KStandardGuiItem::no(),
932 "ekos_shutdown_PTPCamera")))
936 p.
start(
"killall PTPCamera");
944 auto executeStartINDIServices = [
this]()
946 appendLogText(
i18n(
"Starting INDI services..."));
948 m_ekosStatus = Ekos::Pending;
949 emit ekosStatusChanged(m_ekosStatus);
951 DriverManager::Instance()->startDevices(managedDrivers);
955 if (isRunning(
"indiserver"))
960 DriverManager::Instance()->stopAllDevices();
963 const QString program =
"pkill";
965 arguments <<
"indiserver";
966 p.
start(program, arguments);
974 executeStartINDIServices();
977 KSMessageBox::Instance()->questionYesNo(
i18n(
"Ekos detected an instance of INDI server running. Do you wish to "
978 "shut down the existing instance before starting a new one?"),
979 i18n(
"INDI Server"), 5);
982 executeStartINDIServices();
987 auto runConnection = [
this]()
990 if (m_ekosStatus != Ekos::Pending)
994 i18n(
"Connecting to remote INDI server at %1 on port %2 ...", m_CurrentProfile->host, m_CurrentProfile->port));
996 DriverManager::Instance()->connectRemoteHost(managedDrivers.first());
999 auto runProfile = [
this, runConnection]()
1002 if (m_ekosStatus != Ekos::Pending)
1005 INDI::WebManager::syncCustomDrivers(m_CurrentProfile);
1006 INDI::WebManager::checkVersion(m_CurrentProfile);
1008 if (INDI::WebManager::areDriversRunning(m_CurrentProfile) ==
false)
1010 INDI::WebManager::stopProfile(m_CurrentProfile);
1012 if (INDI::WebManager::startProfile(m_CurrentProfile) ==
false)
1014 appendLogText(
i18n(
"Failed to start profile on remote INDI Web Manager."));
1018 appendLogText(
i18n(
"Starting profile on remote INDI Web Manager..."));
1019 m_RemoteManagerStart =
true;
1025 m_ekosStatus = Ekos::Pending;
1026 emit ekosStatusChanged(m_ekosStatus);
1029 if (m_CurrentProfile->INDIWebManagerPort > 0)
1031 appendLogText(
i18n(
"Establishing communication with remote INDI Web Manager..."));
1032 m_RemoteManagerStart =
false;
1039 if (m_ekosStatus != Ekos::Pending)
1051 appendLogText(i18n(
"Warning: INDI Web Manager is not online."));
1057 QFuture<bool> result = INDI::AsyncWebManager::isOnline(m_CurrentProfile);
1067void Manager::setClientStarted(
const QString &host,
int port)
1069 if (managedDrivers.size() > 0)
1073 if (m_CurrentProfile->autoConnect)
1074 appendLogText(
i18n(
"INDI services started on port %1.", port));
1077 i18n(
"INDI services started on port %1. Please connect devices.", port));
1082 i18n(
"INDI services started. Connection to remote INDI server %1:%2 is successful. Waiting for devices...", host, port));
1089void Manager::setClientFailed(
const QString &host,
int port,
const QString &errorMessage)
1092 appendLogText(
i18n(
"Failed to connect to local INDI server %1:%2", host, port));
1094 appendLogText(
i18n(
"Failed to connect to remote INDI server %1:%2", host, port));
1099 m_ekosStatus = Ekos::Error;
1100 emit ekosStatusChanged(m_ekosStatus);
1101 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1104void Manager::setClientTerminated(
const QString &host,
int port,
const QString &errorMessage)
1107 appendLogText(
i18n(
"Lost connection to local INDI server %1:%2", host, port));
1109 appendLogText(
i18n(
"Lost connection to remote INDI server %1:%2", host, port));
1114 m_ekosStatus = Ekos::Error;
1115 emit ekosStatusChanged(m_ekosStatus);
1116 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1119void Manager::setServerStarted(
const QString &host,
int port)
1121 if (m_LocalMode && m_CurrentProfile->indihub != INDIHub::None)
1123 if (
QFile(Options::iNDIHubAgent()).exists())
1128 args <<
"--indi-server" <<
QString(
"%1:%2").
arg(host).
arg(port);
1129 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
1130 args <<
"--phd2-server" <<
QString(
"%1:%2").
arg(m_CurrentProfile->guiderhost).
arg(m_CurrentProfile->guiderport);
1131 args <<
"--mode" << INDIHub::toString(m_CurrentProfile->indihub);
1132 indiHubAgent->start(Options::iNDIHubAgent(), args);
1134 qCDebug(KSTARS_EKOS) <<
"Started INDIHub agent.";
1139void Manager::setServerFailed(
const QString &host,
int port,
const QString &message)
1143 managedDrivers.clear();
1144 m_ekosStatus = Ekos::Error;
1145 emit ekosStatusChanged(m_ekosStatus);
1146 KSNotification::error(message,
i18n(
"Error"), 15);
1167void Manager::checkINDITimeout()
1170 if (m_ekosStatus != Ekos::Pending)
1173 if (m_indiStatus != Ekos::Pending || m_CurrentProfile->portSelector || m_CurrentProfile->autoConnect ==
false)
1179 if (oneDevice->isConnected() ==
false)
1180 disconnectedDevices << oneDevice->getDeviceName();
1185 if (disconnectedDevices.
count() == 1)
1186 message =
i18n(
"Failed to connect to %1. Please ensure device is connected and powered on.", disconnectedDevices.
first());
1188 message =
i18n(
"Failed to connect to \n%1\nPlease ensure each device is connected and powered on.",
1189 disconnectedDevices.
join(
"\n"));
1191 appendLogText(message);
1192 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1197 if (m_DriverDevicesCount <= 0)
1199 m_ekosStatus = Ekos::Success;
1200 emit ekosStatusChanged(m_ekosStatus);
1207 for (
auto &drv : managedDrivers)
1209 if (drv->getDevices().count() == 0)
1211 drv->getUniqueLabel().isEmpty() ==
false ? drv->getUniqueLabel() : drv->getName());
1214 if (remainingDevices.
count() == 1)
1216 QString message =
i18n(
"Unable to establish:\n%1\nPlease ensure the device is connected and powered on.",
1217 remainingDevices.
at(0));
1218 appendLogText(message);
1219 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1224 QString message =
i18n(
"Unable to establish the following devices:\n%1\nPlease ensure each device is connected "
1225 "and powered on.", remainingDevices.
join(
"\n"));
1226 appendLogText(message);
1227 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1235 for (
auto &driver : m_CurrentProfile->drivers.values())
1237 bool driverFound =
false;
1241 if (device->getBaseDevice().getDriverName() == driver)
1248 if (driverFound ==
false)
1249 remainingDevices <<
QString(
"+ %1").
arg(driver);
1252 if (remainingDevices.
count() == 1)
1254 QString message =
i18n(
"Unable to remotely establish:\n%1\nPlease ensure the device is connected and powered on.",
1255 remainingDevices.
at(0));
1256 appendLogText(message);
1257 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1262 QString message =
i18n(
"Unable to remotely establish the following devices:\n%1\nPlease ensure each device is connected "
1263 "and powered on.", remainingDevices.
join(
"\n"));
1264 appendLogText(message);
1265 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1270 m_ekosStatus = Ekos::Error;
1273bool Manager::isINDIReady()
1278 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1280 auto devices = INDIListener::devices();
1281 for (
auto &device : devices)
1284 if (device->isConnected() && device->isReady())
1287 if (devices.count() == nConnected)
1289 m_indiStatus = Ekos::Success;
1290 emit indiStatusChanged(m_indiStatus);
1294 m_indiStatus = Ekos::Pending;
1295 if (previousStatus != m_indiStatus)
1296 emit indiStatusChanged(m_indiStatus);
1301void Manager::connectDevices()
1306 auto devices = INDIListener::devices();
1308 for (
auto &device : devices)
1310 qCDebug(KSTARS_EKOS) <<
"Connecting " << device->getDeviceName();
1314 connectB->setEnabled(
false);
1315 disconnectB->setEnabled(
true);
1317 appendLogText(
i18n(
"Connecting INDI devices..."));
1320void Manager::disconnectDevices()
1324 qCDebug(KSTARS_EKOS) <<
"Disconnecting " << device->getDeviceName();
1325 device->Disconnect();
1328 appendLogText(
i18n(
"Disconnecting INDI devices..."));
1331void Manager::cleanDevices(
bool stopDrivers)
1333 if (m_ekosStatus == Ekos::Idle)
1337 mountModule()->stopTimers();
1339 ekosLiveClient->message()->setPendingPropertiesEnabled(
false);
1343 if (managedDrivers.isEmpty() ==
false)
1348 DriverManager::Instance()->stopDevices(managedDrivers);
1354 DriverManager::Instance()->disconnectRemoteHost(managedDrivers.first());
1356 if (m_RemoteManagerStart && m_CurrentProfile->INDIWebManagerPort != -1)
1357 INDI::WebManager::stopProfile(m_CurrentProfile);
1359 m_RemoteManagerStart =
false;
1365 profileGroup->setEnabled(
true);
1367 appendLogText(
i18n(
"INDI services stopped."));
1372 qCInfo(KSTARS_EKOS) <<
"Ekos received a new device: " << device->getDeviceName();
1374 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1386 m_indiStatus = Ekos::Idle;
1387 if (previousStatus != m_indiStatus)
1388 emit indiStatusChanged(m_indiStatus);
1390 m_DriverDevicesCount--;
1408 connect(device.
get(), &ISD::GenericDevice::propertyDeleted,
this, &Ekos::Manager::processDeleteProperty,
1410 connect(device.
get(), &ISD::GenericDevice::propertyUpdated,
this, &Ekos::Manager::processUpdateProperty,
1418 if (m_CurrentProfile->ccd() != m_CurrentProfile->guider())
1423 m_PrimaryCamera =
QString(oneCamera->getDeviceName());
1424 else if (oneCamera->getDeviceName().startsWith(m_CurrentProfile->guider(),
Qt::CaseInsensitive))
1425 m_GuideCamera =
QString(oneCamera->getDeviceName());
1429 if (m_DriverDevicesCount <= 0)
1431 m_ekosStatus = Ekos::Success;
1432 emit ekosStatusChanged(m_ekosStatus);
1434 connectB->setEnabled(
true);
1435 disconnectB->setEnabled(
false);
1437 if (m_LocalMode ==
false && m_DriverDevicesCount == 0)
1439 if (m_CurrentProfile->autoConnect)
1440 appendLogText(
i18n(
"Remote devices established."));
1442 appendLogText(
i18n(
"Remote devices established. Please connect devices."));
1447void Manager::deviceConnected()
1449 connectB->setEnabled(
false);
1450 disconnectB->setEnabled(
true);
1451 processINDIB->setEnabled(
false);
1453 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1455 if (Options::verboseLogging())
1457 qCInfo(KSTARS_EKOS) << device->getDeviceName()
1458 <<
"Version:" << device->getDriverVersion()
1459 <<
"Interface:" << device->getDriverInterface()
1463 if (Options::neverLoadConfig() ==
false)
1465 INDIConfig tConfig = Options::loadConfigOnConnection() ? LOAD_LAST_CONFIG : LOAD_DEFAULT_CONFIG;
1469 if (oneDevice == device)
1473 auto configProp = device->getBaseDevice().getSwitch(
"CONFIG_PROCESS");
1474 if (configProp && configProp.getState() == IPS_IDLE)
1475 device->setConfig(tConfig);
1482void Manager::deviceDisconnected()
1486 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1490 if (dev->getState(
"CONNECTION") == IPS_ALERT)
1491 m_indiStatus = Ekos::Error;
1492 else if (dev->getState(
"CONNECTION") == IPS_BUSY)
1493 m_indiStatus = Ekos::Pending;
1495 m_indiStatus = Ekos::Idle;
1497 if (Options::verboseLogging())
1498 qCDebug(KSTARS_EKOS) << dev->getDeviceName() <<
" is disconnected.";
1501 if (m_indiStatus == Ekos::Error)
1503 QString message =
i18n(
"%1 failed to connect.\nPlease ensure the device is connected and powered on.",
1504 dev->getDeviceName());
1505 appendLogText(message);
1506 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1508 else if (m_indiStatus == Ekos::Idle)
1510 QString message =
i18n(
"%1 is disconnected.", dev->getDeviceName());
1511 appendLogText(message);
1515 m_indiStatus = Ekos::Idle;
1517 if (previousStatus != m_indiStatus)
1518 emit indiStatusChanged(m_indiStatus);
1520 connectB->setEnabled(
true);
1521 disconnectB->setEnabled(
false);
1522 processINDIB->setEnabled(
true);
1527 ekosLiveClient->message()->sendScopes();
1529 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1531 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1536 ekosLiveClient.get()->media()->registerCameras();
1538 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1540 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1543void Manager::addFilterWheel(ISD::FilterWheel * device)
1546 appendLogText(
i18n(
"%1 filter is online.", name));
1548 createFilterManager(device);
1550 emit newDevice(name, device->getDriverInterface());
1555 appendLogText(
i18n(
"%1 focuser is online.", device->getDeviceName()));
1557 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1562 appendLogText(
i18n(
"Rotator %1 is online.", device->getDeviceName()));
1566 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1569void Manager::addDome(
ISD::Dome * device)
1571 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1573 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1578 appendLogText(
i18n(
"%1 Weather is online.", device->getDeviceName()));
1580 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1583void Manager::addGPS(ISD::GPS * device)
1585 appendLogText(
i18n(
"%1 GPS is online.", device->getDeviceName()));
1587 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1592 OpticalTrainManager::Instance()->syncDevices();
1594 appendLogText(
i18n(
"%1 Dust cap is online.", device->getDeviceName()));
1596 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1601 appendLogText(
i18n(
"%1 Light box is online.", device->getDeviceName()));
1603 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1608 createModules(device);
1613 auto camera = device->getCamera();
1619 if (camera->hasCooler())
1622 if (INDIListener::findDevice(camera->getDeviceName(), generic))
1623 focusModule()->addTemperatureSource(generic);
1632 auto mount = device->getMount();
1638 if (INDIListener::findDevice(
mount->getDeviceName(), generic))
1640 mountModule()->addTimeSource(generic);
1641 mountModule()->addLocationSource(generic);
1650 auto focuser = device->getFocuser();
1657 if (INDIListener::findDevice(focuser->getDeviceName(), generic))
1658 focusModule()->addTemperatureSource(generic);
1673 auto dome = device->getDome();
1677 captureProcess->setDome(dome);
1679 alignProcess->setDome(dome);
1680 if (observatoryProcess)
1681 observatoryProcess->setDome(dome);
1687 auto weather = device->getWeather();
1690 if (observatoryProcess)
1691 observatoryProcess->addWeatherSource(weather);
1696 if (INDIListener::findDevice(weather->getDeviceName(), generic))
1697 focusModule()->addTemperatureSource(generic);
1704 auto gps = device->getGPS();
1710 if (INDIListener::findDevice(gps->getDeviceName(), generic))
1712 mountModule()->addTimeSource(generic);
1713 mountModule()->addLocationSource(generic);
1723 alignModule()->removeDevice(device);
1725 captureProcess->removeDevice(device);
1727 focusModule()->removeDevice(device);
1729 mountModule()->removeDevice(device);
1731 guideProcess->removeDevice(device);
1732 if (observatoryProcess)
1733 observatoryProcess->removeDevice(device);
1735 m_PortSelector->removeDevice(device->getDeviceName());
1737 DarkLibrary::Instance()->removeDevice(device);
1740 for (
auto &oneManager : m_FilterManagers)
1742 oneManager->removeDevice(device);
1746 for (
auto &oneController : m_RotatorControllers)
1748 oneController->close();
1751 appendLogText(
i18n(
"%1 is offline.", device->getDeviceName()));
1754 if (INDIListener::devices().isEmpty())
1761void Manager::processDeleteProperty(INDI::Property prop)
1763 ekosLiveClient.get()->message()->processDeleteProperty(prop);
1766void Manager::processMessage(
int id)
1773 if (!INDIListener::findDevice(origin->getDeviceName(), device))
1776 ekosLiveClient.
get()->message()->processMessage(device,
id);
1779void Manager::processUpdateProperty(INDI::Property prop)
1781 ekosLiveClient.get()->message()->processUpdateProperty(prop);
1783 if (prop.isNameMatch(
"CCD_INFO") ||
1784 prop.isNameMatch(
"GUIDER_INFO") ||
1785 prop.isNameMatch(
"CCD_FRAME") ||
1786 prop.isNameMatch(
"GUIDER_FRAME"))
1788 if (focusModule() !=
nullptr && focusModule()->camera() == prop.getDeviceName())
1789 focusModule()->syncCameraInfo();
1791 if (guideModule() !=
nullptr && guideModule()->camera() == prop.getDeviceName())
1792 guideModule()->syncCameraInfo();
1794 if (alignModule() !=
nullptr && alignModule()->camera() == prop.getDeviceName())
1795 alignModule()->syncCameraInfo();
1801void Manager::processNewProperty(INDI::Property prop)
1804 if (!INDIListener::findDevice(prop.getDeviceName(), device))
1807 settleTimer.start();
1809 ekosLiveClient.
get()->message()->processNewProperty(prop);
1811 if (prop.isNameMatch(
"DEVICE_PORT_SCAN") || prop.isNameMatch(
"CONNECTION_TYPE"))
1813 if (!m_PortSelector)
1818 m_PortSelectorTimer.start();
1819 portSelectorB->setEnabled(
true);
1820 m_PortSelector->addDevice(device);
1825 if (prop.isNameMatch(
"DEBUG"))
1827 uint16_t
interface = device->getDriverInterface();
1828 if ( opsLogs->getINDIDebugInterface() & interface )
1831 auto debugSP = prop.getSwitch();
1832 debugSP->at(0)->setState(ISS_ON);
1833 debugSP->at(1)->setState(ISS_OFF);
1834 device->sendNewProperty(debugSP);
1840 if (prop.isNameMatch(
"DEBUG_LEVEL"))
1842 uint16_t
interface = device->getDriverInterface();
1844 if ( opsLogs->getINDIDebugInterface() & interface )
1847 auto debugLevel = prop.getSwitch();
1848 for (
auto &it : *debugLevel)
1849 it.setState(ISS_ON);
1851 device->sendNewProperty(debugLevel);
1856 if (prop.isNameMatch(
"ASTROMETRY_SOLVER"))
1860 if (oneDevice->getDeviceName() == prop.getDeviceName())
1863 alignModule()->setAstrometryDevice(oneDevice);
1871 if (focusModule() !=
nullptr && strstr(prop.getName(),
"FOCUS_"))
1873 focusModule()->checkFocuser();
1878void Manager::processTabChange()
1880 auto currentWidget = toolsWidget->currentWidget();
1882 if (alignProcess && alignModule() == currentWidget)
1884 auto alignReady = alignModule()->isEnabled() ==
false && alignModule()->isParserOK();
1885 auto captureReady = captureProcess && captureModule()->isEnabled();
1886 auto mountReady = mountProcess && mountModule()->isEnabled();
1887 if (alignReady && captureReady && mountReady)
1888 alignModule()->setEnabled(
true);
1890 alignModule()->checkCamera();
1892 else if (captureProcess && currentWidget == captureModule())
1894 captureModule()->process()->checkCamera();
1896 else if (focusProcess && currentWidget == focusModule())
1898 focusModule()->checkCamera();
1900 else if (guideProcess && currentWidget == guideModule())
1902 guideModule()->checkCamera();
1908void Manager::updateLog()
1910 QWidget * currentWidget = toolsWidget->currentWidget();
1912 if (currentWidget == setupTab)
1913 ekosLogOut->setPlainText(m_LogText.join(
"\n"));
1914 else if (currentWidget == alignModule())
1915 ekosLogOut->setPlainText(alignModule()->getLogText());
1916 else if (currentWidget == captureModule())
1917 ekosLogOut->setPlainText(captureModule()->getLogText());
1918 else if (currentWidget == focusModule())
1919 ekosLogOut->setPlainText(focusModule()->getLogText());
1920 else if (currentWidget == guideModule())
1921 ekosLogOut->setPlainText(guideModule()->getLogText());
1922 else if (currentWidget == mountModule())
1923 ekosLogOut->setPlainText(mountModule()->getLogText());
1924 else if (currentWidget == schedulerModule())
1925 ekosLogOut->setPlainText(schedulerModule()->moduleState()->getLogText());
1926 else if (currentWidget == observatoryProcess.get())
1927 ekosLogOut->setPlainText(observatoryProcess->getLogText());
1928 else if (currentWidget == analyzeProcess.get())
1929 ekosLogOut->setPlainText(analyzeProcess->getLogText());
1936void Manager::appendLogText(
const QString &text)
1938 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
1939 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
1941 qCInfo(KSTARS_EKOS) << text;
1948void Manager::clearLog()
1950 QWidget * currentWidget = toolsWidget->currentWidget();
1952 if (currentWidget == setupTab)
1957 else if (currentWidget == alignModule())
1958 alignModule()->clearLog();
1959 else if (currentWidget == captureModule())
1960 captureModule()->clearLog();
1961 else if (currentWidget == focusModule())
1962 focusModule()->clearLog();
1963 else if (currentWidget == guideModule())
1964 guideModule()->clearLog();
1965 else if (currentWidget == mountModule())
1966 mountModule()->clearLog();
1967 else if (currentWidget == schedulerModule())
1968 schedulerModule()->moduleState()->clearLog();
1969 else if (currentWidget == observatoryProcess.get())
1970 observatoryProcess->clearLog();
1971 else if (currentWidget == analyzeProcess.get())
1972 analyzeProcess->clearLog();
1975void Manager::initCapture()
1977 if (captureModule() !=
nullptr)
1980 captureProcess.reset(
new Capture());
1982 emit newModule(
"Capture");
1985 if (mountModule() !=
nullptr)
1986 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
1988 capturePreview->shareCaptureModule(captureModule());
1989 int index = addModuleTab(EkosModule::Capture, captureModule(),
QIcon(
":/icons/ekos_ccd.png"));
1990 toolsWidget->tabBar()->setTabToolTip(index,
i18nc(
"Charge-Coupled Device",
"CCD"));
1991 if (Options::ekosLeftIcons())
1995 QIcon icon = toolsWidget->tabIcon(index);
1998 toolsWidget->setTabIcon(index, icon);
2000 connect(captureModule(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2001 connect(captureModule(), &Ekos::Capture::newLog,
this, [
this]()
2005 {
"log", captureModule()->getLogText()}
2008 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2010 connect(captureModule(), &Ekos::Capture::newStatus,
this, &Ekos::Manager::updateCaptureStatus);
2011 connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
2012 connect(captureModule(), &Ekos::Capture::driverTimedout,
this, &Ekos::Manager::restartDriver);
2013 connect(captureModule(), &Ekos::Capture::newExposureProgress,
this, &Ekos::Manager::updateExposureProgress);
2014 capturePreview->setEnabled(
true);
2017 connect(captureModule(), &Ekos::Capture::newFilterStatus, capturePreview->captureStatusWidget,
2018 &LedStatusWidget::setFilterState);
2021 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
2023 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
this, [
this](
double distance)
2025 capturePreview->updateTargetDistance(distance);
2032void Manager::initAlign()
2034 if (alignModule() !=
nullptr)
2037 alignProcess.reset(
new Ekos::Align(m_CurrentProfile));
2039 emit newModule(
"Align");
2041 int index = addModuleTab(EkosModule::Align, alignModule(),
QIcon(
":/icons/ekos_align.png"));
2042 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Align"));
2043 connect(alignModule(), &Ekos::Align::newLog,
this, &Ekos::Manager::updateLog);
2044 connect(alignModule(), &Ekos::Align::newLog,
this, [
this]()
2048 {
"log", alignModule()->getLogText()}
2051 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2053 if (Options::ekosLeftIcons())
2057 QIcon icon = toolsWidget->tabIcon(index);
2060 toolsWidget->setTabIcon(index, icon);
2066void Manager::initFocus()
2068 if (focusModule() !=
nullptr)
2073 emit newModule(
"Focus");
2075 int index = addModuleTab(EkosModule::Focus, focusModule(),
QIcon(
":/icons/ekos_focus.png"));
2077 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2080 connect(focusModule(), &Ekos::Focus::newLog,
this, &Ekos::Manager::updateLog);
2081 connect(focusModule(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2082 connect(focusModule(), &Ekos::Focus::newStarPixmap, focusManager, &Ekos::FocusManager::updateFocusStarPixmap);
2083 connect(focusModule(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2085 connect(focusModule(), &Ekos::Focus::newLog,
this, [
this]()
2089 {
"log", focusModule()->getLogText()}
2092 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2094 connect(focusModule(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2098 {
"focusAdvisorMessage", message}
2101 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2103 connect(focusModule(), &Ekos::Focus::newFocusAdvisorStage, ekosLiveClient.get()->message(),
2106 QJsonObject cStatus =
2108 {
"focusAdvisorStage", stage}
2111 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2126 if (Options::ekosLeftIcons())
2130 QIcon icon = toolsWidget->tabIcon(index);
2133 toolsWidget->setTabIcon(index, icon);
2136 focusManager->init();
2137 focusManager->setEnabled(
true);
2141 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2142 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2143 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2144 if (prop1 || prop2 || prop3)
2145 focusModule()->addTemperatureSource(oneDevice);
2151void Manager::updateCurrentHFR(
double newHFR,
int position,
bool inAutofocus)
2153 Q_UNUSED(inAutofocus);
2154 focusManager->updateCurrentHFR(newHFR);
2162 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2165void Manager::updateSigmas(
double ra,
double de)
2167 guideManager->updateSigmas(ra, de);
2169 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2171 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2174void Manager::initMount()
2176 if (mountModule() !=
nullptr)
2182 if (captureModule() !=
nullptr)
2183 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2185 emit newModule(
"Mount");
2187 int index = addModuleTab(EkosModule::Mount, mountModule(),
QIcon(
":/icons/ekos_mount.png"));
2189 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2190 connect(mountModule(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2197 connect(mountModule(), &Ekos::Mount::pierSideChanged,
this, [&](ISD::Mount::PierSide side)
2199 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"pierSide", side}}));
2201 connect(mountModule()->getMeridianFlipState().
get(),
2202 &Ekos::MeridianFlipState::newMountMFStatus, [&](MeridianFlipState::MeridianFlipMountState status)
2204 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2206 {
"meridianFlipStatus",
status},
2209 connect(mountModule()->getMeridianFlipState().
get(),
2210 &Ekos::MeridianFlipState::newMeridianFlipMountStatusText, [&](
const QString & text)
2213 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2215 {
"meridianFlipText", text},
2216 }), mountModule()->getMeridianFlipState()->getMeridianFlipMountState() == MeridianFlipState::MOUNT_FLIP_NONE);
2217 meridianFlipStatusWidget->setStatus(text);
2219 connect(mountModule(), &Ekos::Mount::autoParkCountdownUpdated,
this, [&](
const QString & text)
2221 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"autoParkCountdown", text}}),
true);
2224 connect(mountModule(), &Ekos::Mount::trainChanged, ekosLiveClient.get()->message(),
2227 connect(mountModule(), &Ekos::Mount::slewRateChanged,
this, [&](
int slewRate)
2230 ekosLiveClient.get()->message()->updateMountStatus(status);
2233 if (Options::ekosLeftIcons())
2237 QIcon icon = toolsWidget->tabIcon(index);
2240 toolsWidget->setTabIcon(index, icon);
2243 mountGroup->setEnabled(
true);
2244 capturePreview->shareMountModule(mountModule());
2249void Manager::initGuide()
2251 if (guideModule() ==
nullptr)
2255 emit newModule(
"Guide");
2258 if (toolsWidget->indexOf(guideModule()) == -1)
2263 int index = addModuleTab(EkosModule::Guide, guideModule(),
QIcon(
":/icons/ekos_guide.png"));
2264 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2265 connect(guideModule(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2266 connect(guideModule(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2268 guideManager->setEnabled(
true);
2270 connect(guideModule(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2271 connect(guideModule(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2272 connect(guideModule(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2273 connect(guideModule(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2276 ekosLiveClient.get()->message()->updateGuideStatus(status);
2278 connect(guideModule(), &Ekos::Guide::newLog, ekosLiveClient.get()->message(),
2281 QJsonObject cStatus =
2283 {
"log", guideModule()->getLogText()}
2286 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2289 if (Options::ekosLeftIcons())
2293 QIcon icon = toolsWidget->tabIcon(index);
2296 toolsWidget->setTabIcon(index, icon);
2298 guideManager->init(guideModule());
2304void Manager::initObservatory()
2306 if (observatoryProcess.get() ==
nullptr)
2309 observatoryProcess.reset(
new Ekos::Observatory());
2311 emit newModule(
"Observatory");
2313 int index = addModuleTab(EkosModule::Observatory, observatoryProcess.get(),
QIcon(
":/icons/ekos_observatory.png"));
2314 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Observatory"));
2315 connect(observatoryProcess.get(), &Ekos::Observatory::newLog,
this, &Ekos::Manager::updateLog);
2317 if (Options::ekosLeftIcons())
2321 QIcon icon = toolsWidget->tabIcon(index);
2324 toolsWidget->setTabIcon(index, icon);
2329void Manager::addGuider(ISD::Guider * device)
2331 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2334void Manager::removeTabs()
2338 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2339 toolsWidget->removeTab(i);
2341 alignProcess.reset();
2342 captureProcess.reset();
2343 focusProcess.reset();
2344 guideProcess.reset();
2345 mountProcess.reset();
2346 observatoryProcess.reset();
2351bool Manager::isRunning(
const QString &process)
2358 return output.
length() > 0;
2363 <<
"-C" << process);
2370void Manager::addObjectToScheduler(
SkyObject *
object)
2372 if (schedulerModule() !=
nullptr)
2373 schedulerModule()->addObject(
object);
2376QString Manager::getCurrentJobName()
2378 return schedulerModule()->getCurrentJobName();
2381bool Manager::setProfile(
const QString &profileName)
2383 int index = profileCombo->findText(profileName);
2388 profileCombo->setCurrentIndex(index);
2393void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2395 ProfileEditor editor(
this);
2396 setProfile(profileInfo[
"name"].
toString());
2397 if (getCurrentProfile(m_CurrentProfile))
2399 editor.setPi(m_CurrentProfile);
2400 editor.setSettings(profileInfo);
2401 editor.saveProfile();
2405void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2407 ProfileEditor editor(
this);
2409 editor.setSettings(profileInfo);
2410 editor.saveProfile();
2413 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2414 getCurrentProfile(m_CurrentProfile);
2417void Manager::deleteNamedProfile(
const QString &name)
2419 if (!getCurrentProfile(m_CurrentProfile))
2422 for (
auto &pi : profiles)
2426 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == m_CurrentProfile && ekosStatus() != Idle))
2429 KStarsData::Instance()->
userdb()->PurgeProfile(pi);
2432 getCurrentProfile(m_CurrentProfile);
2442 for (
auto &pi : profiles)
2444 if (name == pi->name)
2445 return pi->toJson();
2455 for (
int i = 0; i < profileCombo->count(); i++)
2456 profiles << profileCombo->itemText(i);
2461void Manager::addProfile()
2463 ProfileEditor editor(
this);
2469 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2472 getCurrentProfile(m_CurrentProfile);
2475void Manager::editProfile()
2477 ProfileEditor editor(
this);
2479 if (getCurrentProfile(m_CurrentProfile))
2482 editor.setPi(m_CurrentProfile);
2486 int currentIndex = profileCombo->currentIndex();
2490 profileCombo->setCurrentIndex(currentIndex);
2493 getCurrentProfile(m_CurrentProfile);
2497void Manager::deleteProfile()
2499 if (!getCurrentProfile(m_CurrentProfile))
2502 if (m_CurrentProfile->name ==
"Simulators")
2505 auto executeDeleteProfile = [&]()
2507 KStarsData::Instance()->
userdb()->PurgeProfile(m_CurrentProfile);
2510 getCurrentProfile(m_CurrentProfile);
2517 executeDeleteProfile();
2520 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2521 i18n(
"Confirm Delete"));
2525void Manager::wizardProfile()
2531 ProfileEditor editor(
this);
2533 editor.setProfileName(wz.profileName);
2534 editor.setAuxDrivers(wz.selectedAuxDrivers());
2535 if (wz.useInternalServer ==
false)
2536 editor.setHostPort(wz.host, wz.port);
2537 editor.setWebManager(wz.useWebManager);
2538 editor.setGuiderType(wz.selectedExternalGuider());
2540 editor.setConnectionOptionsEnabled(
false);
2546 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2549 getCurrentProfile(m_CurrentProfile);
2555 for (
auto &pi : profiles)
2557 if (profileCombo->currentText() == pi->name)
2569 if (profile->city.isEmpty() ==
false)
2573 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2575 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2580void Manager::updateMountStatus(ISD::Mount::Status status)
2582 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2584 if (status == lastStatus)
2589 mountStatus->setMountState(mountModule()->statusString(), status);
2590 mountStatus->setStyleSheet(
QString());
2594 {
"status", mountModule()->statusString(
false)}
2597 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2600void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2619 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2624 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), devicename);
2633 m_CountdownTimer.stop();
2636 m_CountdownTimer.start();
2645 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2646 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2650 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2656 capturePreview->updateJobProgress(job, data, devicename);
2660 {
"seqv", job->getCompleted()},
2661 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).
toInt()},
2662 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2665 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2667 if (data && job->getStatus() == JOB_BUSY)
2671 if (Options::useFITSViewer() ==
false)
2672 ekosLiveClient.get()->media()->sendData(data, data->objectName());
2674 if (job->jobType() != SequenceJob::JOBTYPE_PREVIEW)
2675 ekosLiveClient.get()->cloud()->upload(data, data->objectName());
2679void Manager::updateExposureProgress(Ekos::SequenceJob * job,
const QString &devicename)
2683 {
"expv", job->getExposeLeft()},
2684 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).
toDouble()},
2688 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2691void Manager::updateCaptureCountDown()
2693 capturePreview->updateCaptureCountDown(-1);
2697 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2698 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2699 {
"ovp", capturePreview->captureCountsWidget->gr_overallProgressBar->value()},
2700 {
"ovl", capturePreview->captureCountsWidget->gr_overallLabel->text()}
2703 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2707void Manager::updateFocusStatus(Ekos::FocusState status)
2709 focusManager->updateFocusStatus(status);
2713 {
"status", getFocusStatusString(status,
false)}
2716 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2719void Manager::updateGuideStatus(Ekos::GuideState status)
2721 guideManager->updateGuideStatus(status);
2724 {
"status", getGuideStatusString(status,
false)}
2727 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2730void Manager::setTarget(
const QString &name)
2732 capturePreview->targetLabel->setVisible(!
name.
isEmpty());
2733 capturePreview->mountTarget->setVisible(!
name.
isEmpty());
2734 capturePreview->mountTarget->setText(name);
2735 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"target",
name}}));
2738 mountModule()->setTargetName(name);
2741void Manager::showEkosOptions()
2743 QWidget * currentWidget = toolsWidget->currentWidget();
2745 if (alignModule() && alignModule() == currentWidget)
2751 alignSettings->
show();
2756 if (guideModule() && guideModule() == currentWidget)
2762 if (focusModule() && focusModule() == currentWidget)
2767 focusSettings->
show();
2768 focusSettings->
raise();
2773 const bool isCapture = (captureModule() && captureModule() == currentWidget);
2774 const bool isScheduler = (schedulerModule() && schedulerModule() == currentWidget);
2775 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
2776 if (isCapture || isScheduler || isAnalyze)
2781 if (isScheduler) index = 1;
2782 else if (isCapture) index = 2;
2783 else if (isAnalyze) index = 3;
2784 opsEkos->setCurrentIndex(index);
2797 if (ekosOptionsWidget ==
nullptr)
2814void Manager::updateDebugInterfaces()
2820 auto debugProp = device->getProperty(
"DEBUG");
2824 auto debugSP = debugProp.getSwitch();
2827 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2828 debugSP->sp[0].s != ISS_ON)
2830 debugSP->at(0)->setState(ISS_ON);
2831 debugSP->at(1)->setState(ISS_OFF);
2833 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
2835 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2836 debugSP->sp[0].s != ISS_OFF)
2838 debugSP->at(0)->setState(ISS_OFF);
2839 debugSP->at(1)->setState(ISS_ON);
2841 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
2844 if (opsLogs->isINDISettingsChanged())
2845 device->setConfig(SAVE_CONFIG);
2849void Manager::watchDebugProperty(INDI::Property prop)
2851 if (prop.isNameMatch(
"DEBUG"))
2853 auto svp = prop.getSwitch();
2858 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
2863 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
2864 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
2866 svp->sp[0].s = ISS_ON;
2867 svp->sp[1].s = ISS_OFF;
2868 deviceInterface->sendNewProperty(svp);
2869 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
2875 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
2876 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
2878 svp->sp[0].s = ISS_OFF;
2879 svp->sp[1].s = ISS_ON;
2880 deviceInterface->sendNewProperty(svp);
2881 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
2886void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
2888 ekosLiveClient.get()->message()->sendEvent(message, source, event);
2891void Manager::connectModules()
2894 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
2896 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
2898 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
2900 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
2904 if (captureProcess && guideProcess)
2910 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
2916 connect(captureModule(), &Ekos::Capture::newStatus, guideModule(), &Ekos::Guide::setCaptureStatus,
2924 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
2930 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
2935 if (guideProcess && mountProcess)
2946 if (guideProcess && focusProcess)
2954 if (captureProcess && focusProcess)
2981 connect(focusModule(), &Ekos::Focus::focusAdaptiveComplete, captureModule(),
2989 connect(focusModule(), &Ekos::Focus::newFocusTemperatureDelta, captureModule(),
2998 if (captureProcess && alignProcess)
3001 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3004 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3007 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3012 if (captureProcess && mountProcess)
3016 captureModule()->registerNewModule(
"Mount");
3017 mountModule()->registerNewModule(
"Capture");
3033 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3035 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3040 if (captureProcess && ekosLiveClient)
3044 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3046 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3048 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3050 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3052 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3057 if (focusProcess && alignProcess)
3059 connect(focusModule(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3064 if (focusProcess && mountProcess)
3073 if (mountProcess && alignProcess)
3086 if (mountProcess && guideProcess)
3088 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3093 if (alignProcess && ekosLiveClient)
3098 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3100 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3102 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3103 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3105 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3106 ekosLiveClient.get()->message(),
3108 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3109 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3111 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3112 ekosLiveClient.get()->message(),
3114 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3115 ekosLiveClient.get()->message(),
3117 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3118 ekosLiveClient.get()->media(),
3121 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3123 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3126 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3129 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3132 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3137 if (focusProcess && ekosLiveClient)
3139 connect(focusModule(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3142 connect(focusModule(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3145 connect(focusModule(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3146 &EkosLive::Message::sendTrainProfiles,
3149 connect(focusModule(), &Ekos::Focus::autofocusAborted,
3154 if (guideProcess && ekosLiveClient)
3156 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3159 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3162 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3170 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3172 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3174 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3180 connect(captureModule(), &Ekos::Capture::captureComplete,
3182 connect(captureModule(), &Ekos::Capture::captureStarting,
3184 connect(captureModule(), &Ekos::Capture::captureAborted,
3188 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3190 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3198 connect(guideModule(), &Ekos::Guide::newStatus,
3201 connect(guideModule(), &Ekos::Guide::guideStats,
3208 if (focusProcess && analyzeProcess)
3210 connect(focusModule(), &Ekos::Focus::autofocusComplete,
3214 connect(focusModule(), &Ekos::Focus::autofocusStarting,
3216 connect(focusModule(), &Ekos::Focus::autofocusAborted,
3218 connect(focusModule(), &Ekos::Focus::newFocusTemperatureDelta,
3223 if (alignProcess && analyzeProcess)
3225 connect(alignModule(), &Ekos::Align::newStatus,
3231 if (mountProcess && analyzeProcess)
3237 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3242void Manager::setEkosLiveConnected(
bool enabled)
3244 ekosLiveClient.get()->setConnected(enabled);
3247void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3249 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3252void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3254 ekosLiveClient.get()->setUser(username, password);
3257bool Manager::ekosLiveStatus()
3259 return ekosLiveClient.get()->isConnected();
3265 if (!primaryDriver || !secondaryDriver)
3268 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3269 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3272void Manager::restartDriver(
const QString &deviceName)
3274 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3279 if (oneDevice->getDeviceName() == deviceName)
3281 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3287 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3290void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3293 if (name ==
"LOGGING")
3295 Options::setDisableLogging(!enabled);
3299 else if (name ==
"FILE")
3301 Options::setLogToFile(enabled);
3305 else if (name ==
"DEFAULT")
3307 Options::setLogToDefault(enabled);
3312 else if (name ==
"VERBOSE")
3314 Options::setVerboseLogging(enabled);
3318 else if (name ==
"INDI")
3320 Options::setINDILogging(enabled);
3323 else if (name ==
"FITS")
3325 Options::setFITSLogging(enabled);
3328 else if (name ==
"CAPTURE")
3330 Options::setCaptureLogging(enabled);
3331 Options::setINDICCDLogging(enabled);
3332 Options::setINDIFilterWheelLogging(enabled);
3335 else if (name ==
"FOCUS")
3337 Options::setFocusLogging(enabled);
3338 Options::setINDIFocuserLogging(enabled);
3341 else if (name ==
"GUIDE")
3343 Options::setGuideLogging(enabled);
3344 Options::setINDICCDLogging(enabled);
3347 else if (name ==
"ALIGNMENT")
3349 Options::setAlignmentLogging(enabled);
3352 else if (name ==
"MOUNT")
3354 Options::setMountLogging(enabled);
3355 Options::setINDIMountLogging(enabled);
3358 else if (name ==
"SCHEDULER")
3360 Options::setSchedulerLogging(enabled);
3363 else if (name ==
"OBSERVATORY")
3365 Options::setObservatoryLogging(enabled);
3370void Manager::acceptPortSelection()
3373 m_PortSelector->accept();
3376void Manager::setPortSelectionComplete()
3378 if (m_CurrentProfile->portSelector)
3381 m_CurrentProfile->portSelector =
false;
3382 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3385 if (m_CurrentProfile->autoConnect)
3389void Manager::activateModule(
const QString &name,
bool popup)
3391 auto child = toolsWidget->findChild<
QWidget *>(
name);
3394 toolsWidget->setCurrentWidget(child);
3406 if (device->isConnected())
3408 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3415 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3421 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3423 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3430 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3435 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3441 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3446 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3450 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3454 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3461void Manager::setDeviceReady()
3465 if (isINDIReady() ==
false)
3471 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3474 if (m_CurrentProfile->portSelector)
3480 if (!m_PortSelector)
3481 m_PortSelectorTimer.start();
3485 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3490 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3493 if (m_ekosStatus != Ekos::Success)
3498 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3501 syncGenericDevice(device);
3502 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3506void Manager::createFilterManager(ISD::FilterWheel *device)
3508 auto name = device->getDeviceName();
3509 if (m_FilterManagers.contains(name) ==
false)
3512 newFM->setFilterWheel(device);
3513 m_FilterManagers[
name] = newFM;
3516 m_FilterManagers[
name]->setFilterWheel(device);
3522 if (m_FilterManagers.contains(name))
3524 fm = m_FilterManagers[
name];
3532 if (m_FilterManagers.size() > 0)
3534 fm = m_FilterManagers.values()[0];
3540void Manager::createRotatorController(
ISD::Rotator *device)
3542 auto Name = device->getDeviceName();
3543 if (m_RotatorControllers.contains(Name) ==
false)
3547 m_RotatorControllers[Name] = newRC;
3553 if (m_RotatorControllers.contains(Name))
3555 rs = m_RotatorControllers[Name];
3561bool Manager::existRotatorController()
3563 return (!m_RotatorControllers.empty());
DriverInfo holds all metadata associated with a particular INDI driver.
DriverManager is the primary class to handle all operations related to starting and stopping INDI dri...
Align class handles plate-solving and polar alignment measurement and correction using astrometry....
Analysis tab for Ekos sessions.
void setFocusTemperatureDelta(double focusTemperatureDelta, double absTemperature)
updateAdaptiveFocusStatus Handle new focus state
void setHFR(double newHFR, int position, bool inAutofocus)
setHFR Receive the measured HFR value of the latest frame
void updateTargetDistance(double targetDiff)
Slot receiving the update of the current target distance.
void setFocusStatus(FocusState newstate)
setFocusStatus Forward the new focus state to the capture module state machine
void setGuideDeviation(double delta_ra, double delta_dec)
setGuideDeviation Set the guiding deviation as measured by the guiding module.
void focusAdaptiveComplete(bool success)
focusAdaptiveComplete Forward the new focus state to the capture module state machine
Supports manual focusing and auto focusing using relative and absolute INDI focusers.
void drawPolynomial(PolynomialFit *poly, bool isVShape, bool activate, bool plot=true)
draw the approximating polynomial into the HFR V-graph
void newHFRPlotPosition(double pos, double hfr, double sigma, bool outlier, int pulseDuration, bool plot=true)
new HFR plot position with sigma
void redrawHFRPlot(PolynomialFit *poly, double solutionPosition, double solutionValue)
redraw the entire HFR plot
void runAutoFocus(const AutofocusReason autofocusReason, const QString &reasonInfo)
Run the autofocus process for the currently selected filter.
void focuserTimedout(const QString &focuser)
focuserTimedout responding to requests
void initHFRPlot(QString str, double starUnits, bool minimum, bool useWeights, bool showPosition)
initialize the HFR V plot
void adaptiveFocus()
adaptiveFocus moves the focuser between subframes to stay at focus
Q_SCRIPTABLE Q_NOREPLY void resetFrame()
DBUS interface function.
void meridianFlipStarted()
React when a meridian flip has been started.
void drawCFZ(double minPosition, double minValue, int m_cfzSteps, bool plt)
Draw Critical Focus Zone on graph.
void finalUpdates(const QString &title, bool plot=true)
final updates after focus run comopletes on the focus plot
void minimumFound(double solutionPosition, double solutionValue, bool plot=true)
Focus solution with minimal HFR found.
void setTitle(const QString &title, bool plot=true)
draw a title on the focus plot
void drawCurve(CurveFitting *curve, bool isVShape, bool activate, bool plot=true)
draw the curve into the HFR V-graph
void adaptiveFocusComplete(const QString &filter, double temperature, double tempTicks, double altitude, double altTicks, int prevPosError, int thisPosError, int totalTicks, int position, bool focuserMoved)
Signal Analyze that an Adaptive Focus iteration is complete.
Performs calibration and autoguiding using an ST4 port or directly via the INDI driver.
Q_SCRIPTABLE bool resume()
DBUS interface function.
Q_SCRIPTABLE bool suspend()
DBUS interface function.
Q_SCRIPTABLE bool abort()
DBUS interface function.
Supports controlling INDI telescope devices including setting/retrieving mount properties,...
void newTarget(SkyPoint ¤tCoord)
The mount has finished the slew to a new target.
void paaStageChanged(int stage)
React upon status changes of the polar alignment - mainly to avoid meridian flips happening during po...
void newTargetName(const QString &name)
The mount has finished the slew to a new target.
void newStatus(ISD::Mount::Status status)
Change in the mount status.
void suspendAltLimits()
suspendAltLimits calls enableAltitudeLimits(false).
void newCoords(const SkyPoint &position, ISD::Mount::PierSide pierSide, const dms &ha)
Update event with the current telescope position.
void resumeAltLimits()
resumeAltLimits calls enableAltitudeLimits(true).
Enables the user to set logging options.
INDIListener is responsible for creating ISD::GDInterface generic devices as new devices arrive from ...
Camera class controls an INDI Camera device.
void sendNewProperty(INDI::Property prop)
Send new property command to server.
Class handles control of INDI dome devices.
Handles operation of a remotely controlled dust cover cap.
Focuser class handles control of INDI focuser devices.
GenericDevice is the Generic Device for INDI devices.
Handles operation of a remotely controlled light box.
device handle controlling Mounts.
Rotator class handles control of INDI Rotator devices.
Focuser class handles control of INDI Weather devices.
Q_INVOKABLE QAction * action(const QString &name) const
static bool showDialog(const QString &name)
KPageWidgetItem * addPage(QWidget *page, const QString &itemName, const QString &pixmapName=QString(), const QString &header=QString(), bool manage=true)
static KConfigDialog * exists(const QString &name)
static void beep(const QString &reason=QString())
QPushButton * button(QDialogButtonBox::StandardButton which) const
void setCurrentPage(KPageWidgetItem *item)
void setIcon(const QIcon &icon)
bool GetAllProfiles(QList< QSharedPointer< ProfileInfo > > &profiles)
GetAllProfiles Return all profiles in a QList.
static void UseDefault()
Use the default logging mechanism.
static void SyncFilterRules()
SyncFilterRules Sync QtLogging filter rules from Options.
static void Disable()
Disable logging.
static void UseFile()
Store all logs into the specified file.
Q_INVOKABLE SimClock * clock()
This is the main window for KStars.
static KStars * Instance()
Q_SCRIPTABLE bool setGeoLocation(const QString &city, const QString &province, const QString &country)
DBUS interface function.
virtual KActionCollection * actionCollection() const
Primary class to handle all Ekos modules.
void setRealTime(bool on=true)
Realtime mode will lock SimClock with system clock.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
The sky coordinates of a point in the sky.
const CachingDms & dec() const
const CachingDms & ra0() const
const CachingDms & ra() const
const CachingDms & dec0() const
An angle, stored as degrees, but expressible in many ways.
static dms fromString(const QString &s, bool deg)
Static function to create a DMS object from a QString.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
const double & Degrees() const
void setTarget(const SkyPoint &targetCoord)
Set the alignment target where the mount is expected to point at.
void setTelescopeCoordinates(const SkyPoint &position)
Set the coordinates that the mount reports as its position.
Q_SCRIPTABLE Q_NOREPLY void checkFocus(double requiredHFR)
checkFocus Given the minimum required HFR, check focus and calculate HFR.
Q_SCRIPTABLE Q_NOREPLY void abort()
DBUS interface function.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString fullName(const PartType &type)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
CaptureState
Capture states.
QString name(GameStandardAction id)
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
GeoCoordinates geo(const QVariant &location)
QVariant location(const QVariant &res)
QString label(StandardShortcut id)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void currentTextChanged(const QString &text)
QCoreApplication * instance()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
void setFuture(const QFuture< T > &future)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
void append(const QJsonValue &value)
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
qsizetype count() const const
bool isEmpty() const const
qsizetype length() const const
bool disconnect(const QMetaObject::Connection &connection)
QByteArray readAllStandardOutput()
void start(OpenMode mode)
bool waitForFinished(int msecs)
QString & append(QChar ch)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString join(QChar separator) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
double toDouble(bool *ok) const const
int toInt(bool *ok) const const