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 "focus/focusmodule.h"
16#include "align/align.h"
17#include "guide/guide.h"
18#include "mount/mount.h"
19#include "observatory/observatory.h"
22#include "ekosadaptor.h"
24#include "kstarsdata.h"
26#include "ekos/capture/rotatorsettings.h"
27#include "profileeditor.h"
28#include "profilewizard.h"
30#include "auxiliary/darklibrary.h"
31#include "auxiliary/ksmessagebox.h"
32#include "auxiliary/profilesettings.h"
33#include "capture/sequencejob.h"
34#include "capture/cameraprocess.h"
35#include "fitsviewer/fitsview.h"
36#include "fitsviewer/fitsdata.h"
37#include "indi/clientmanager.h"
38#include "indi/driverinfo.h"
39#include "indi/drivermanager.h"
40#include "indi/guimanager.h"
41#include "indi/indilistener.h"
42#include "auxiliary/opticaltrainmanager.h"
43#include "auxiliary/opticaltrainsettings.h"
44#include "indi/indiwebmanager.h"
45#include "indi/indigps.h"
46#include "indi/indiguider.h"
47#include "indi/indirotator.h"
48#include "mount/meridianflipstatuswidget.h"
49#include "ekos/auxiliary/rotatorutils.h"
51#include "ekoslive/ekosliveclient.h"
52#include "ekoslive/message.h"
53#include "ekoslive/media.h"
55#include <basedevice.h>
57#include <KConfigDialog>
59#include <KActionCollection>
60#include <knotification.h>
62#include <QFutureWatcher>
65#include <ekos_debug.h>
67#define MAX_REMOTE_INDI_TIMEOUT 15000
68#define MAX_LOCAL_INDI_TIMEOUT 10000
73Manager *Manager::_Manager =
nullptr;
77 if (_Manager ==
nullptr)
83void Manager::release()
85 ProfileSettings::release();
86 OpticalTrainManager::release();
87 OpticalTrainSettings::release();
88 RotatorUtils::release();
96 if (Options::independentWindowEkos())
105 if (Options::independentWindowEkos())
111 capturePreview->targetLabel->setVisible(
false);
112 capturePreview->mountTarget->setVisible(
false);
115 deviceSplitter->setSizes(
QList<int>({20000, 10000}));
117 qRegisterMetaType<Ekos::CommunicationStatus>(
"Ekos::CommunicationStatus");
118 qDBusRegisterMetaType<Ekos::CommunicationStatus>();
120 new EkosAdaptor(
this);
126 profileModel->setHorizontalHeaderLabels(
QStringList() <<
"id"
131 m_CountdownTimer.setInterval(1000);
134 toolsWidget->setIconSize(
QSize(48, 48));
138 toolsWidget->setTabEnabled(1,
false);
141 toolsWidget->setTabEnabled(2,
false);
146 processINDIB->setToolTip(
i18n(
"Start"));
154 ekosLiveClient.reset(
new EkosLive::Client(
this));
155 connect(ekosLiveClient.get(), &EkosLive::Client::connected,
this, [
this]()
157 emit ekosLiveStatusChanged(true);
159 connect(ekosLiveClient.get(), &EkosLive::Client::disconnected,
this, [
this]()
161 emit ekosLiveStatusChanged(false);
168 ekosLiveClient.get()->show();
169 ekosLiveClient.get()->raise();
172 connect(
this, &Manager::ekosStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setEkosStatingStatus);
173 connect(
this, &Manager::indiStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setINDIStatus);
174 connect(ekosLiveClient.get()->message(), &EkosLive::Message::connected,
this, [&]()
176 ekosLiveB->setIcon(QIcon(
":/icons/cloud-online.svg"));
178 connect(ekosLiveClient.get()->message(), &EkosLive::Message::disconnected,
this, [&]()
180 ekosLiveB->setIcon(QIcon::fromTheme(
"folder-cloud"));
182 connect(ekosLiveClient.get()->media(), &EkosLive::Media::newBoundingRect, ekosLiveClient.get()->message(),
183 &EkosLive::Message::setBoundingRect);
184 connect(ekosLiveClient.get()->message(), &EkosLive::Message::resetPolarView, ekosLiveClient.get()->media(),
185 &EkosLive::Media::resetPolarView);
186 connect(KSMessageBox::Instance(), &KSMessageBox::newMessage, ekosLiveClient.get()->message(),
187 &EkosLive::Message::sendDialog);
190 m_PortSelectorTimer.setInterval(500);
191 m_PortSelectorTimer.setSingleShot(
true);
194 if (m_PortSelector && m_CurrentProfile->portSelector)
196 if (m_PortSelector->shouldShow())
198 m_PortSelector->show();
199 m_PortSelector->raise();
201 ekosLiveClient.get()->message()->requestPortSelection(
true);
204 else if (m_CurrentProfile->autoConnect)
205 setPortSelectionComplete();
207 else if (m_CurrentProfile->autoConnect)
208 setPortSelectionComplete();
214 m_PortSelector->show();
215 m_PortSelector->raise();
219 connect(
this, &Ekos::Manager::ekosStatusChanged,
this, [&](Ekos::CommunicationStatus status)
221 indiControlPanelB->setEnabled(status == Ekos::Success);
222 connectB->setEnabled(
false);
223 disconnectB->setEnabled(
false);
224 extensionB->setEnabled(
false);
225 extensionCombo->setEnabled(
false);
226 profileGroup->setEnabled(status == Ekos::Idle || status == Ekos::Error);
227 m_isStarted = (
status == Ekos::Success ||
status == Ekos::Pending);
228 if (status == Ekos::Success)
231 processINDIB->setToolTip(
i18n(
"Stop"));
232 setWindowTitle(
i18nc(
"@title:window",
"Ekos - %1 Profile", m_CurrentProfile->name));
234 else if (status == Ekos::Error || status == Ekos::Idle)
237 processINDIB->setToolTip(
i18n(
"Start"));
242 processINDIB->setToolTip(
i18n(
"Connection in progress. Click to abort."));
275 Options::setProfile(text);
276 if (text ==
"Simulators")
278 editProfileB->setEnabled(
false);
279 deleteProfileB->setEnabled(
false);
283 editProfileB->setEnabled(
true);
284 deleteProfileB->setEnabled(
true);
290 settleTimer.setInterval(1000);
293 if (m_settleStatus != Ekos::Success)
295 m_settleStatus = Ekos::Success;
296 emit settleStatusChanged(m_settleStatus);
332 toolsWidget->tabBar()->setTabIcon(0,
QIcon(
":/icons/ekos_setup.png"));
333 toolsWidget->tabBar()->setTabToolTip(0,
i18n(
"Setup"));
336 schedulerProcess.reset(
new Scheduler());
337 int index = addModuleTab(EkosModule::Scheduler, schedulerModule(),
QIcon(
":/icons/ekos_scheduler.png"));
338 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Scheduler"));
339 capturePreview->shareSchedulerModuleState(schedulerModule()->moduleState());
340 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog,
this, &Ekos::Manager::updateLog);
341 connect(schedulerModule(), &Ekos::Scheduler::newTarget,
this, &Manager::setTarget);
343 connect(schedulerModule(), &Ekos::Scheduler::jobsUpdated, ekosLiveClient.get()->message(),
345 connect(schedulerModule(), &Ekos::Scheduler::settingsUpdated, ekosLiveClient.get()->message(),
347 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog, ekosLiveClient.get()->message(),
350 QJsonObject cStatus =
352 {
"log", schedulerModule()->moduleState()->getLogText()}
355 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
357 connect(schedulerModule(), &Ekos::Scheduler::newStatus, ekosLiveClient.get()->message(),
358 [
this](Ekos::SchedulerState state)
360 QJsonObject cStatus =
365 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
370 connect(analyzeProcess.get(), &Ekos::Analyze::newLog,
this, &Ekos::Manager::updateLog);
372 index = addModuleTab(EkosModule::Analyze, analyzeProcess.get(),
QIcon(
":/icons/ekos_analyze.png"));
373 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Analyze"));
375 numPermanentTabs = index + 1;
378 extensionTimer.setSingleShot(
true);
379 groupBox_4->setHidden(
true);
383 if (extensionB->icon().name() ==
"media-playback-start")
385 extensionTimer.setInterval(1000);
388 appendLogText(
i18n(
"Extension '%1' failed to start, aborting", extensionCombo->currentText()));
391 extensionTimer.start();
392 extensionAbort =
false;
393 m_extensions.run(extensionCombo->currentText());
395 else if (extensionB->icon().name() ==
"media-playback-stop")
399 extensionTimer.setInterval(10000);
402 appendLogText(
i18n(
"Extension '%1' failed to stop, abort enabled", extensionCombo->currentText()));
403 extensionB->setEnabled(
true);
404 extensionAbort =
true;
406 extensionTimer.start();
411 appendLogText(
i18n(
"Extension '%1' aborting", extensionCombo->currentText()));
416 connect(&m_extensions, &extensions::extensionStateChanged,
this, [
this](Ekos::ExtensionState state)
420 case EXTENSION_START_REQUESTED:
421 appendLogText(
i18n(
"Extension '%1' start requested", extensionCombo->currentText()));
422 extensionB->setEnabled(
false);
423 extensionCombo->setEnabled(
false);
425 case EXTENSION_STARTED:
426 appendLogText(
i18n(
"Extension '%1' started", extensionCombo->currentText()));
428 extensionB->setEnabled(
true);
429 extensionCombo->setEnabled(
false);
430 extensionTimer.stop();
433 case EXTENSION_STOP_REQUESTED:
434 appendLogText(
i18n(
"Extension '%1' stop requested", extensionCombo->currentText()));
435 extensionB->setEnabled(
false);
436 extensionCombo->setEnabled(
false);
438 case EXTENSION_STOPPED:
439 appendLogText(
i18n(
"Extension '%1' stopped", extensionCombo->currentText()));
441 extensionB->setEnabled(
true);
442 extensionCombo->setEnabled(
true);
443 extensionTimer.stop();
446 m_extensionStatus = state;
447 emit extensionStatusChanged();
451 extensionCombo->setToolTip(m_extensions.getTooltip(text));
453 connect(&m_extensions, &extensions::extensionOutput,
this, [
this] (
QString message)
455 appendLogText(
QString(
i18n(
"Extension '%1': %2", extensionCombo->currentText(), message.
trimmed())));
464 m_SummaryView.reset(
new SummaryFITSView(capturePreview->previewWidget));
468 m_SummaryView->createFloatingToolBar();
469 m_SummaryView->setCursorMode(FITSView::dragCursor);
470 m_SummaryView->showProcessInfo(
false);
471 capturePreview->setSummaryFITSView(m_SummaryView);
474 if (Options::ekosLeftIcons())
480 for (
int i = 0; i < numPermanentTabs; ++i)
482 QIcon icon = toolsWidget->tabIcon(i);
485 toolsWidget->setTabIcon(i, icon);
493 for (
auto &button : qButtons)
494 button->setAutoDefault(
false);
497 resize(Options::ekosWindowWidth(), Options::ekosWindowHeight());
514 toolsWidget->disconnect(
this);
531 Options::setEkosWindowWidth(width());
532 Options::setEkosWindowHeight(height());
544 if (profileWizardLaunched ==
false && profiles.count() == 1)
546 profileWizardLaunched =
true;
553 focusProgressWidget->updateFocusDetailView();
554 guideManager->updateGuideDetailView();
557void Manager::loadProfiles()
562 profileModel->clear();
564 for (
auto &pi : profiles)
570 profileModel->appendRow(info);
573 profileModel->sort(0);
574 profileCombo->blockSignals(
true);
575 profileCombo->setModel(profileModel.get());
576 profileCombo->setModelColumn(1);
577 profileCombo->blockSignals(
false);
580 int index = profileCombo->findText(Options::profile());
584 profileCombo->setCurrentIndex(index);
587int Manager::addModuleTab(Manager::EkosModule module,
QWidget *tab,
const QIcon &icon)
592 case EkosModule::Observatory:
593 index += guideProcess ? 1 : 0;
594 case EkosModule::Guide:
595 index += alignProcess ? 1 : 0;
596 case EkosModule::Align:
597 index += mountProcess ? 1 : 0;
598 case EkosModule::Mount:
599 index += focusProcess ? 1 : 0;
600 case EkosModule::Focus:
601 index += captureProcess ? 1 : 0;
602 case EkosModule::Capture:
603 index += analyzeProcess ? 1 : 0;
604 case EkosModule::Analyze:
605 index += schedulerProcess ? 1 : 0;
606 case EkosModule::Scheduler:
608 case EkosModule::Setup:
612 index = toolsWidget->count();
616 toolsWidget->insertTab(index, tab, icon,
"");
620void Manager::loadDrivers()
622 for (
auto &dv : DriverManager::Instance()->getDrivers())
624 if (dv->getDriverSource() != HOST_SOURCE)
625 driversList[dv->getLabel()] = dv;
631 qCDebug(KSTARS_EKOS) <<
"Resetting Ekos Manager...";
633 ProfileSettings::release();
634 OpticalTrainManager::release();
635 OpticalTrainSettings::release();
636 RotatorUtils::release();
638 m_DriverDevicesCount = 0;
642 captureProcess.reset();
643 focusProcess.reset();
644 guideProcess.reset();
645 alignProcess.reset();
646 mountProcess.reset();
647 observatoryProcess.reset();
649 for (
auto &oneManger : m_FilterManagers)
651 m_FilterManagers.clear();
653 for (
auto &oneController : m_RotatorControllers)
654 oneController.reset();
655 m_RotatorControllers.clear();
657 DarkLibrary::Release();
658 m_PortSelector.reset();
659 m_PortSelectorTimer.stop();
661 Ekos::CommunicationStatus previousStatus;
663 previousStatus = m_settleStatus;
664 m_settleStatus = Ekos::Idle;
665 if (previousStatus != m_settleStatus)
666 emit settleStatusChanged(m_settleStatus);
668 previousStatus = m_ekosStatus;
669 m_ekosStatus = Ekos::Idle;
670 if (previousStatus != m_ekosStatus)
671 emit ekosStatusChanged(m_ekosStatus);
673 previousStatus = m_indiStatus;
674 m_indiStatus = Ekos::Idle;
675 if (previousStatus != m_indiStatus)
676 emit indiStatusChanged(m_indiStatus);
678 connectB->setEnabled(
false);
679 disconnectB->setEnabled(
false);
680 extensionB->setEnabled(
false);
681 extensionCombo->setEnabled(
false);
683 processINDIB->setEnabled(
true);
685 mountGroup->setEnabled(
false);
686 capturePreview->setEnabled(
false);
687 capturePreview->reset();
689 mountStatus->setStyleSheet(
QString());
690 focusProgressWidget->reset();
691 guideManager->reset();
696 processINDIB->setToolTip(
i18n(
"Start"));
699void Manager::processINDI()
701 if (m_isStarted ==
false)
710 m_PortSelector.reset();
711 m_PortSelectorTimer.stop();
712 m_CountdownTimer.stop();
713 portSelectorB->setEnabled(
false);
716 indiHubAgent->terminate();
718 profileGroup->setEnabled(
true);
720 setWindowTitle(
i18nc(
"@title:window",
"Ekos"));
723 extensionCombo->clear();
724 m_extensions.found->clear();
725 groupBox_4->setHidden(
true);
730 if (analyzeProcess && Options::analyzeRestartWithEkos())
731 analyzeProcess->restart();
734 if (m_ekosStatus == Ekos::Pending || m_ekosStatus == Ekos::Success)
736 qCWarning(KSTARS_EKOS) <<
"Ekos Manager start called but current Ekos Status is" << m_ekosStatus <<
"Ignoring request.";
740 managedDrivers.clear();
749 getCurrentProfile(m_CurrentProfile);
750 m_LocalMode = m_CurrentProfile->isLocal();
752 ProfileSettings::Instance()->setProfile(m_CurrentProfile);
755 updateProfileLocation(m_CurrentProfile);
757 bool haveCCD =
false, haveGuider =
false;
761 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
763 Options::setPHD2Host(m_CurrentProfile->guiderhost);
764 Options::setPHD2Port(m_CurrentProfile->guiderport);
766 else if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_LINGUIDER)
768 Options::setLinGuiderHost(m_CurrentProfile->guiderhost);
769 Options::setLinGuiderPort(m_CurrentProfile->guiderport);
778 profileScripts = doc.
array();
780 ekosLiveClient->message()->setPendingPropertiesEnabled(
true);
785 auto drv = driversList.value(m_CurrentProfile->mount());
788 managedDrivers.append(drv->clone());
790 drv = driversList.value(m_CurrentProfile->ccd());
793 managedDrivers.append(drv->clone());
797 Options::setGuiderType(m_CurrentProfile->guidertype);
799 drv = driversList.value(m_CurrentProfile->guider());
810 if (haveCCD && m_CurrentProfile->guider() == m_CurrentProfile->ccd())
812 if (checkUniqueBinaryDriver( driversList.value(m_CurrentProfile->ccd()), drv))
818 drv->setUniqueLabel(drv->getLabel() +
" Guide");
823 managedDrivers.append(drv->clone());
826 drv = driversList.value(m_CurrentProfile->ao());
828 managedDrivers.append(drv->clone());
830 drv = driversList.value(m_CurrentProfile->filter());
832 managedDrivers.append(drv->clone());
834 drv = driversList.value(m_CurrentProfile->focuser());
836 managedDrivers.append(drv->clone());
838 drv = driversList.value(m_CurrentProfile->dome());
840 managedDrivers.append(drv->clone());
842 drv = driversList.value(m_CurrentProfile->weather());
844 managedDrivers.append(drv->clone());
846 drv = driversList.value(m_CurrentProfile->aux1());
849 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
850 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
851 managedDrivers.append(drv->clone());
853 drv = driversList.value(m_CurrentProfile->aux2());
856 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
857 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
858 managedDrivers.append(drv->clone());
861 drv = driversList.value(m_CurrentProfile->aux3());
864 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
865 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
866 managedDrivers.append(drv->clone());
869 drv = driversList.value(m_CurrentProfile->aux4());
872 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
873 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
874 managedDrivers.append(drv->clone());
878 if (m_CurrentProfile->remotedrivers.isEmpty() ==
false && m_CurrentProfile->remotedrivers.contains(
"@"))
880 for (
auto remoteDriver : m_CurrentProfile->remotedrivers.split(
","))
882 QString name,
label, host(
"localhost"), port(
"7624"), hostport(host +
':' + port);
892 QStringList device_location = remoteDriver.split(
'@');
895 if (device_location.
length() > 0)
896 name = device_location[0];
899 if (device_location.
length() > 1)
900 hostport = device_location[1];
916 dv->setRemoteHost(host);
917 dv->setRemotePort(port);
923 dv->setUniqueLabel(label);
924 managedDrivers.
append(dv);
929 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
931 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
932 managedDrivers.clear();
933 m_ekosStatus = Ekos::Error;
934 emit ekosStatusChanged(m_ekosStatus);
938 m_DriverDevicesCount = managedDrivers.count();
944 remote_indi->setHostParameters(m_CurrentProfile->host, m_CurrentProfile->port);
946 remote_indi->setDriverSource(GENERATED_SOURCE);
948 managedDrivers.append(remote_indi);
950 haveCCD = m_CurrentProfile->drivers.contains(
"CCD");
951 haveGuider = m_CurrentProfile->drivers.contains(
"Guider");
953 Options::setGuiderType(m_CurrentProfile->guidertype);
955 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
957 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
958 m_DriverDevicesCount = 0;
959 m_ekosStatus = Ekos::Error;
960 emit ekosStatusChanged(m_ekosStatus);
964 m_DriverDevicesCount = m_CurrentProfile->drivers.count();
970 for (
const auto &oneRule : qAsConst(profileScripts))
972 auto driver = oneRule.toObject()[
"Driver"].toString();
973 auto matchingDriver = std::find_if(managedDrivers.begin(), managedDrivers.end(), [oneRule, driver](
const auto & oneDriver)
976 return oneDriver->getLabel() == driver || (driver.startsWith(
"@") && !oneDriver->getRemoteHost().isEmpty());
979 if (matchingDriver != managedDrivers.end())
981 (*matchingDriver)->setStartupRule(oneRule.toObject());
982 sortedList.
append(*matchingDriver);
990 for (
auto &oneDriver : managedDrivers)
992 if (sortedList.
contains(oneDriver) ==
false)
993 sortedList.
append(oneDriver);
996 managedDrivers = sortedList;
999 connect(DriverManager::Instance(), &DriverManager::serverStarted,
this,
1001 connect(DriverManager::Instance(), &DriverManager::serverFailed,
this,
1003 connect(DriverManager::Instance(), &DriverManager::clientStarted,
this,
1005 connect(DriverManager::Instance(), &DriverManager::clientFailed,
this,
1007 connect(DriverManager::Instance(), &DriverManager::clientTerminated,
this,
1010 connect(INDIListener::Instance(), &INDIListener::newDevice,
this, &Ekos::Manager::processNewDevice);
1015 if (m_LocalMode || m_CurrentProfile->host ==
"localhost")
1017 if (isRunning(
"PTPCamera"))
1020 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?"),
1021 i18n(
"PTP Camera")))
1025 p.
start(
"killall PTPCamera");
1033 auto executeStartINDIServices = [
this]()
1035 appendLogText(
i18n(
"Starting INDI services..."));
1037 m_ekosStatus = Ekos::Pending;
1038 emit ekosStatusChanged(m_ekosStatus);
1040 DriverManager::Instance()->startDevices(managedDrivers);
1044 if (isRunning(
"indiserver"))
1049 DriverManager::Instance()->stopAllDevices();
1052 const QString program =
"pkill";
1054 arguments <<
"indiserver";
1055 p.
start(program, arguments);
1063 executeStartINDIServices();
1066 KSMessageBox::Instance()->questionYesNo(
i18n(
"Ekos detected an instance of INDI server running. Do you wish to "
1067 "shut down the existing instance before starting a new one?"),
1068 i18n(
"INDI Server"), 5);
1071 executeStartINDIServices();
1076 auto runConnection = [
this]()
1079 if (m_ekosStatus != Ekos::Pending)
1083 i18n(
"Connecting to remote INDI server at %1 on port %2 ...", m_CurrentProfile->host, m_CurrentProfile->port));
1085 DriverManager::Instance()->connectRemoteHost(managedDrivers.first());
1088 auto runProfile = [
this, runConnection]()
1091 if (m_ekosStatus != Ekos::Pending)
1094 INDI::WebManager::syncCustomDrivers(m_CurrentProfile);
1095 INDI::WebManager::checkVersion(m_CurrentProfile);
1097 if (INDI::WebManager::areDriversRunning(m_CurrentProfile) ==
false)
1099 INDI::WebManager::stopProfile(m_CurrentProfile);
1101 if (INDI::WebManager::startProfile(m_CurrentProfile) ==
false)
1103 appendLogText(
i18n(
"Failed to start profile on remote INDI Web Manager."));
1107 appendLogText(
i18n(
"Starting profile on remote INDI Web Manager..."));
1108 m_RemoteManagerStart =
true;
1114 m_ekosStatus = Ekos::Pending;
1115 emit ekosStatusChanged(m_ekosStatus);
1118 if (m_CurrentProfile->INDIWebManagerPort > 0)
1120 appendLogText(
i18n(
"Establishing communication with remote INDI Web Manager..."));
1121 m_RemoteManagerStart =
false;
1128 if (m_ekosStatus != Ekos::Pending)
1140 appendLogText(
i18n(
"Warning: INDI Web Manager is not online."));
1146 QFuture<bool> result = INDI::AsyncWebManager::isOnline(m_CurrentProfile);
1156 if (m_extensions.discover())
1158 foreach (
QString extension, m_extensions.found->keys())
1160 extensions::extDetails m_ext = m_extensions.found->value(extension);
1161 extensionCombo->addItem(m_ext.icon, extension);
1164 if (extensionCombo->count() > 0)
1166 groupBox_4->setHidden(
false);
1170void Manager::setClientStarted(
const QString &host,
int port)
1172 if (managedDrivers.size() > 0)
1176 if (m_CurrentProfile->autoConnect)
1177 appendLogText(
i18n(
"INDI services started on port %1.", port));
1180 i18n(
"INDI services started on port %1. Please connect devices.", port));
1185 i18n(
"INDI services started. Connection to remote INDI server %1:%2 is successful. Waiting for devices...", host, port));
1192void Manager::setClientFailed(
const QString &host,
int port,
const QString &errorMessage)
1195 appendLogText(
i18n(
"Failed to connect to local INDI server %1:%2", host, port));
1197 appendLogText(
i18n(
"Failed to connect to remote INDI server %1:%2", host, port));
1202 m_ekosStatus = Ekos::Error;
1203 emit ekosStatusChanged(m_ekosStatus);
1204 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1207void Manager::setClientTerminated(
const QString &host,
int port,
const QString &errorMessage)
1210 appendLogText(
i18n(
"Lost connection to local INDI server %1:%2", host, port));
1212 appendLogText(
i18n(
"Lost connection to remote INDI server %1:%2", host, port));
1217 m_ekosStatus = Ekos::Error;
1218 emit ekosStatusChanged(m_ekosStatus);
1219 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1222void Manager::setServerStarted(
const QString &host,
int port)
1224 if (m_LocalMode && m_CurrentProfile->indihub != INDIHub::None)
1226 if (
QFile(Options::iNDIHubAgent()).exists())
1231 args <<
"--indi-server" <<
QString(
"%1:%2").
arg(host).
arg(port);
1232 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
1233 args <<
"--phd2-server" <<
QString(
"%1:%2").
arg(m_CurrentProfile->guiderhost).
arg(m_CurrentProfile->guiderport);
1234 args <<
"--mode" << INDIHub::toString(m_CurrentProfile->indihub);
1235 indiHubAgent->start(Options::iNDIHubAgent(), args);
1237 qCDebug(KSTARS_EKOS) <<
"Started INDIHub agent.";
1242void Manager::setServerFailed(
const QString &host,
int port,
const QString &message)
1246 managedDrivers.clear();
1247 m_ekosStatus = Ekos::Error;
1248 emit ekosStatusChanged(m_ekosStatus);
1249 KSNotification::error(message,
i18n(
"Error"), 15);
1270void Manager::checkINDITimeout()
1273 if (m_ekosStatus != Ekos::Pending)
1276 if (m_indiStatus != Ekos::Pending || m_CurrentProfile->portSelector || m_CurrentProfile->autoConnect ==
false)
1280 for (
auto &oneDevice : INDIListener::devices())
1282 if (oneDevice->isConnected() ==
false)
1283 disconnectedDevices << oneDevice->getDeviceName();
1288 if (disconnectedDevices.
count() == 1)
1289 message =
i18n(
"Failed to connect to %1. Please ensure device is connected and powered on.", disconnectedDevices.
first());
1291 message =
i18n(
"Failed to connect to \n%1\nPlease ensure each device is connected and powered on.",
1292 disconnectedDevices.
join(
"\n"));
1294 appendLogText(message);
1295 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1300 if (m_DriverDevicesCount <= 0)
1302 m_ekosStatus = Ekos::Success;
1303 emit ekosStatusChanged(m_ekosStatus);
1310 for (
auto &drv : managedDrivers)
1312 if (drv->getDevices().count() == 0)
1314 drv->getUniqueLabel().isEmpty() ==
false ? drv->getUniqueLabel() : drv->getName());
1317 if (remainingDevices.
count() == 1)
1319 QString message =
i18n(
"Unable to establish:\n%1\nPlease ensure the device is connected and powered on.",
1320 remainingDevices.
at(0));
1321 appendLogText(message);
1322 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1327 QString message =
i18n(
"Unable to establish the following devices:\n%1\nPlease ensure each device is connected "
1328 "and powered on.", remainingDevices.
join(
"\n"));
1329 appendLogText(message);
1330 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1338 for (
auto &driver : m_CurrentProfile->drivers.values())
1340 bool driverFound =
false;
1342 for (
auto &device : INDIListener::devices())
1344 if (device->getBaseDevice().getDriverName() == driver)
1351 if (driverFound ==
false)
1352 remainingDevices <<
QString(
"+ %1").
arg(driver);
1355 if (remainingDevices.
count() == 1)
1357 QString message =
i18n(
"Unable to remotely establish:\n%1\nPlease ensure the device is connected and powered on.",
1358 remainingDevices.
at(0));
1359 appendLogText(message);
1360 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1365 QString message =
i18n(
"Unable to remotely establish the following devices:\n%1\nPlease ensure each device is connected "
1366 "and powered on.", remainingDevices.
join(
"\n"));
1367 appendLogText(message);
1368 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1373 m_ekosStatus = Ekos::Error;
1376bool Manager::isINDIReady()
1381 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1383 auto devices = INDIListener::devices();
1384 for (
auto &device : devices)
1387 if (device->isConnected() && device->isReady())
1390 if (devices.count() == nConnected)
1392 m_indiStatus = Ekos::Success;
1393 emit indiStatusChanged(m_indiStatus);
1397 m_indiStatus = Ekos::Pending;
1398 if (previousStatus != m_indiStatus)
1399 emit indiStatusChanged(m_indiStatus);
1404void Manager::connectDevices()
1409 auto devices = INDIListener::devices();
1411 for (
auto &device : devices)
1413 qCDebug(KSTARS_EKOS) <<
"Connecting " << device->getDeviceName();
1417 connectB->setEnabled(
false);
1418 disconnectB->setEnabled(
true);
1419 extensionCombo->setEnabled(
true);
1420 if (extensionCombo->currentText() !=
"")
1421 extensionB->setEnabled(
true);
1423 appendLogText(
i18n(
"Connecting INDI devices..."));
1426void Manager::disconnectDevices()
1428 for (
auto &device : INDIListener::devices())
1430 qCDebug(KSTARS_EKOS) <<
"Disconnecting " << device->getDeviceName();
1431 device->Disconnect();
1434 appendLogText(
i18n(
"Disconnecting INDI devices..."));
1437void Manager::cleanDevices(
bool stopDrivers)
1439 if (m_ekosStatus == Ekos::Idle)
1443 mountModule()->stopTimers();
1445 ekosLiveClient->message()->setPendingPropertiesEnabled(
false);
1449 if (managedDrivers.isEmpty() ==
false)
1454 DriverManager::Instance()->stopDevices(managedDrivers);
1460 DriverManager::Instance()->disconnectRemoteHost(managedDrivers.first());
1462 if (m_RemoteManagerStart && m_CurrentProfile->INDIWebManagerPort != -1)
1463 INDI::WebManager::stopProfile(m_CurrentProfile);
1465 m_RemoteManagerStart =
false;
1471 profileGroup->setEnabled(
true);
1473 appendLogText(
i18n(
"INDI services stopped."));
1478 qCInfo(KSTARS_EKOS) <<
"Ekos received a new device: " << device->getDeviceName();
1480 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1492 m_indiStatus = Ekos::Idle;
1493 if (previousStatus != m_indiStatus)
1494 emit indiStatusChanged(m_indiStatus);
1496 m_DriverDevicesCount--;
1514 connect(device.
get(), &ISD::GenericDevice::propertyDeleted,
this, &Ekos::Manager::processDeleteProperty,
1516 connect(device.
get(), &ISD::GenericDevice::propertyUpdated,
this, &Ekos::Manager::processUpdateProperty,
1524 if (m_CurrentProfile->ccd() != m_CurrentProfile->guider())
1526 for (
auto &oneCamera : INDIListener::devices())
1529 m_PrimaryCamera =
QString(oneCamera->getDeviceName());
1530 else if (oneCamera->getDeviceName().startsWith(m_CurrentProfile->guider(),
Qt::CaseInsensitive))
1531 m_GuideCamera =
QString(oneCamera->getDeviceName());
1535 if (m_DriverDevicesCount <= 0)
1537 m_ekosStatus = Ekos::Success;
1538 emit ekosStatusChanged(m_ekosStatus);
1540 connectB->setEnabled(
true);
1541 disconnectB->setEnabled(
false);
1542 extensionCombo->setEnabled(
false);
1543 extensionB->setEnabled(
false);
1545 if (m_LocalMode ==
false && m_DriverDevicesCount == 0)
1547 if (m_CurrentProfile->autoConnect)
1548 appendLogText(
i18n(
"Remote devices established."));
1550 appendLogText(
i18n(
"Remote devices established. Please connect devices."));
1555void Manager::deviceConnected()
1557 connectB->setEnabled(
false);
1558 disconnectB->setEnabled(
true);
1559 processINDIB->setEnabled(
false);
1560 extensionCombo->setEnabled(
true);
1561 if (extensionCombo->currentText() !=
"")
1562 extensionB->setEnabled(
true);
1564 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1566 if (Options::verboseLogging())
1568 qCInfo(KSTARS_EKOS) << device->getDeviceName()
1569 <<
"Version:" << device->getDriverVersion()
1570 <<
"Interface:" << device->getDriverInterface()
1574 if (Options::neverLoadConfig() ==
false)
1576 INDIConfig tConfig = Options::loadConfigOnConnection() ? LOAD_LAST_CONFIG : LOAD_DEFAULT_CONFIG;
1578 for (
auto &oneDevice : INDIListener::devices())
1580 if (oneDevice == device)
1584 auto configProp = device->getBaseDevice().getSwitch(
"CONFIG_PROCESS");
1585 if (configProp && configProp.getState() == IPS_IDLE)
1586 device->setConfig(tConfig);
1593void Manager::deviceDisconnected()
1597 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1601 if (dev->getState(
"CONNECTION") == IPS_ALERT)
1602 m_indiStatus = Ekos::Error;
1603 else if (dev->getState(
"CONNECTION") == IPS_BUSY)
1604 m_indiStatus = Ekos::Pending;
1606 m_indiStatus = Ekos::Idle;
1608 if (Options::verboseLogging())
1609 qCDebug(KSTARS_EKOS) << dev->getDeviceName() <<
" is disconnected.";
1612 if (m_indiStatus == Ekos::Error)
1614 QString message =
i18n(
"%1 failed to connect.\nPlease ensure the device is connected and powered on.",
1615 dev->getDeviceName());
1616 appendLogText(message);
1617 KSNotification::event(
QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1619 else if (m_indiStatus == Ekos::Idle)
1621 QString message =
i18n(
"%1 is disconnected.", dev->getDeviceName());
1622 appendLogText(message);
1626 m_indiStatus = Ekos::Idle;
1628 if (previousStatus != m_indiStatus)
1629 emit indiStatusChanged(m_indiStatus);
1631 connectB->setEnabled(
true);
1632 disconnectB->setEnabled(
false);
1633 processINDIB->setEnabled(
true);
1634 extensionCombo->setEnabled(
false);
1635 extensionB->setEnabled(
false);
1640 ekosLiveClient->message()->sendScopes();
1642 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1644 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1649 ekosLiveClient.get()->media()->registerCameras();
1651 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1653 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1656void Manager::addFilterWheel(ISD::FilterWheel * device)
1659 appendLogText(
i18n(
"%1 filter is online.", name));
1661 createFilterManager(device);
1663 emit newDevice(name, device->getDriverInterface());
1668 appendLogText(
i18n(
"%1 focuser is online.", device->getDeviceName()));
1670 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1675 appendLogText(
i18n(
"Rotator %1 is online.", device->getDeviceName()));
1679 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1682void Manager::addDome(
ISD::Dome * device)
1684 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1686 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1691 appendLogText(
i18n(
"%1 Weather is online.", device->getDeviceName()));
1693 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1696void Manager::addGPS(ISD::GPS * device)
1698 appendLogText(
i18n(
"%1 GPS is online.", device->getDeviceName()));
1700 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1705 OpticalTrainManager::Instance()->syncDevices();
1707 appendLogText(
i18n(
"%1 Dust cap is online.", device->getDeviceName()));
1709 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1714 appendLogText(
i18n(
"%1 Light box is online.", device->getDeviceName()));
1716 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1721 createModules(device);
1726 auto camera = device->getCamera();
1732 if (camera->hasCooler())
1735 if (INDIListener::findDevice(camera->getDeviceName(), generic))
1736 focusModule()->addTemperatureSource(generic);
1745 auto mount = device->getMount();
1751 if (INDIListener::findDevice(
mount->getDeviceName(), generic))
1753 mountModule()->addTimeSource(generic);
1754 mountModule()->addLocationSource(generic);
1763 auto focuser = device->getFocuser();
1770 if (INDIListener::findDevice(focuser->getDeviceName(), generic))
1771 focusModule()->addTemperatureSource(generic);
1786 auto dome = device->getDome();
1790 captureProcess->setDome(dome);
1792 alignProcess->setDome(dome);
1793 if (observatoryProcess)
1794 observatoryProcess->setDome(dome);
1800 auto weather = device->getWeather();
1803 if (observatoryProcess)
1804 observatoryProcess->addWeatherSource(weather);
1809 if (INDIListener::findDevice(weather->getDeviceName(), generic))
1810 focusModule()->addTemperatureSource(generic);
1817 auto gps = device->getGPS();
1823 if (INDIListener::findDevice(gps->getDeviceName(), generic))
1825 mountModule()->addTimeSource(generic);
1826 mountModule()->addLocationSource(generic);
1836 alignModule()->removeDevice(device);
1838 captureProcess->removeDevice(device);
1840 focusModule()->removeDevice(device);
1842 mountModule()->removeDevice(device);
1844 guideProcess->removeDevice(device);
1845 if (observatoryProcess)
1846 observatoryProcess->removeDevice(device);
1848 m_PortSelector->removeDevice(device->getDeviceName());
1850 DarkLibrary::Instance()->removeDevice(device);
1853 for (
auto &oneManager : m_FilterManagers)
1855 oneManager->removeDevice(device);
1859 for (
auto &oneController : m_RotatorControllers)
1861 oneController->close();
1864 appendLogText(
i18n(
"%1 is offline.", device->getDeviceName()));
1867 if (INDIListener::devices().isEmpty())
1874void Manager::processDeleteProperty(INDI::Property prop)
1876 ekosLiveClient.get()->message()->processDeleteProperty(prop);
1879void Manager::processMessage(
int id)
1886 if (!INDIListener::findDevice(origin->getDeviceName(), device))
1889 ekosLiveClient.
get()->message()->processMessage(device,
id);
1892void Manager::processUpdateProperty(INDI::Property prop)
1894 ekosLiveClient.get()->message()->processUpdateProperty(prop);
1896 if (prop.isNameMatch(
"CCD_INFO") ||
1897 prop.isNameMatch(
"GUIDER_INFO") ||
1898 prop.isNameMatch(
"CCD_FRAME") ||
1899 prop.isNameMatch(
"GUIDER_FRAME"))
1901 if (focusModule() !=
nullptr)
1902 focusModule()->syncCameraInfo(prop.getDeviceName());
1904 if (guideModule() !=
nullptr && guideModule()->camera() == prop.getDeviceName())
1905 guideModule()->syncCameraInfo();
1907 if (alignModule() !=
nullptr && alignModule()->camera() == prop.getDeviceName())
1908 alignModule()->syncCameraInfo();
1914void Manager::processNewProperty(INDI::Property prop)
1917 if (!INDIListener::findDevice(prop.getDeviceName(), device))
1920 settleTimer.start();
1922 ekosLiveClient.
get()->message()->processNewProperty(prop);
1924 if (prop.isNameMatch(
"DEVICE_PORT_SCAN") || prop.isNameMatch(
"CONNECTION_TYPE"))
1926 if (!m_PortSelector)
1931 m_PortSelectorTimer.start();
1932 portSelectorB->setEnabled(
true);
1933 m_PortSelector->addDevice(device);
1938 if (prop.isNameMatch(
"DEBUG"))
1940 uint16_t
interface = device->getDriverInterface();
1941 if ( opsLogs->getINDIDebugInterface() & interface )
1944 auto debugSP = prop.getSwitch();
1945 debugSP->at(0)->setState(ISS_ON);
1946 debugSP->at(1)->setState(ISS_OFF);
1947 device->sendNewProperty(debugSP);
1953 if (prop.isNameMatch(
"DEBUG_LEVEL"))
1955 uint16_t
interface = device->getDriverInterface();
1957 if ( opsLogs->getINDIDebugInterface() & interface )
1960 auto debugLevel = prop.getSwitch();
1961 for (
auto &it : *debugLevel)
1962 it.setState(ISS_ON);
1964 device->sendNewProperty(debugLevel);
1969 if (prop.isNameMatch(
"ASTROMETRY_SOLVER"))
1971 for (
auto &oneDevice : INDIListener::devices())
1973 if (oneDevice->getDeviceName() == prop.getDeviceName())
1976 alignModule()->setAstrometryDevice(oneDevice);
1984 if (focusModule() !=
nullptr && strstr(prop.getName(),
"FOCUS_"))
1986 focusModule()->checkFocusers();
1991void Manager::processTabChange()
1993 auto currentWidget = toolsWidget->currentWidget();
1995 if (alignProcess && alignModule() == currentWidget)
1997 auto alignReady = alignModule()->isEnabled() ==
false && alignModule()->isParserOK();
1998 auto captureReady = captureProcess && captureModule()->isEnabled();
1999 auto mountReady = mountProcess && mountModule()->isEnabled();
2000 if (alignReady && captureReady && mountReady)
2001 alignModule()->setEnabled(
true);
2003 alignModule()->checkCamera();
2005 else if (captureProcess && currentWidget == captureModule())
2007 captureModule()->process()->checkCamera();
2009 else if (focusProcess && currentWidget == focusModule())
2011 focusModule()->checkCameras();
2013 else if (guideProcess && currentWidget == guideModule())
2015 guideModule()->checkCamera();
2021void Manager::updateLog()
2023 QWidget * currentWidget = toolsWidget->currentWidget();
2025 if (currentWidget == setupTab)
2026 ekosLogOut->setPlainText(m_LogText.join(
"\n"));
2027 else if (currentWidget == alignModule())
2028 ekosLogOut->setPlainText(alignModule()->getLogText());
2029 else if (currentWidget == captureModule())
2030 ekosLogOut->setPlainText(captureModule()->getLogText());
2031 else if (currentWidget == focusModule())
2032 ekosLogOut->setPlainText(focusModule()->getLogText());
2033 else if (currentWidget == guideModule())
2034 ekosLogOut->setPlainText(guideModule()->getLogText());
2035 else if (currentWidget == mountModule())
2036 ekosLogOut->setPlainText(mountModule()->getLogText());
2037 else if (currentWidget == schedulerModule())
2038 ekosLogOut->setPlainText(schedulerModule()->moduleState()->getLogText());
2039 else if (currentWidget == observatoryProcess.get())
2040 ekosLogOut->setPlainText(observatoryProcess->getLogText());
2041 else if (currentWidget == analyzeProcess.get())
2042 ekosLogOut->setPlainText(analyzeProcess->getLogText());
2049void Manager::appendLogText(
const QString &text)
2051 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
2052 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
2054 qCInfo(KSTARS_EKOS) << text;
2061void Manager::clearLog()
2063 QWidget * currentWidget = toolsWidget->currentWidget();
2065 if (currentWidget == setupTab)
2070 else if (currentWidget == alignModule())
2071 alignModule()->clearLog();
2072 else if (currentWidget == captureModule())
2073 captureModule()->clearLog();
2074 else if (currentWidget == focusModule())
2075 focusModule()->clearLog();
2076 else if (currentWidget == guideModule())
2077 guideModule()->clearLog();
2078 else if (currentWidget == mountModule())
2079 mountModule()->clearLog();
2080 else if (currentWidget == schedulerModule())
2081 schedulerModule()->moduleState()->clearLog();
2082 else if (currentWidget == observatoryProcess.get())
2083 observatoryProcess->clearLog();
2084 else if (currentWidget == analyzeProcess.get())
2085 analyzeProcess->clearLog();
2088void Manager::initCapture()
2090 if (captureModule() !=
nullptr)
2093 captureProcess.reset(
new Capture());
2095 emit newModule(
"Capture");
2098 if (mountModule() !=
nullptr)
2099 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2101 capturePreview->shareCaptureModule(captureModule());
2102 int index = addModuleTab(EkosModule::Capture, captureModule(),
QIcon(
":/icons/ekos_ccd.png"));
2103 toolsWidget->tabBar()->setTabToolTip(index,
i18nc(
"Charge-Coupled Device",
"CCD"));
2104 if (Options::ekosLeftIcons())
2108 QIcon icon = toolsWidget->tabIcon(index);
2111 toolsWidget->setTabIcon(index, icon);
2113 connect(captureModule(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2114 connect(captureModule(), &Ekos::Capture::newLog,
this, [
this]()
2118 {
"log", captureModule()->getLogText()}
2121 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2123 connect(captureModule(), &Ekos::Capture::newStatus,
this, &Ekos::Manager::updateCaptureStatus);
2124 connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
2125 connect(captureModule(), &Ekos::Capture::driverTimedout,
this, &Ekos::Manager::restartDriver);
2126 connect(captureModule(), &Ekos::Capture::newExposureProgress,
this, &Ekos::Manager::updateExposureProgress);
2127 capturePreview->setEnabled(
true);
2130 connect(captureModule(), &Ekos::Capture::newFilterStatus, capturePreview->captureStatusWidget,
2131 &LedStatusWidget::setFilterState);
2134 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
2136 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
this, [
this](
double distance)
2138 capturePreview->updateTargetDistance(distance);
2145void Manager::initAlign()
2147 if (alignModule() !=
nullptr)
2150 alignProcess.reset(
new Ekos::Align(m_CurrentProfile));
2152 emit newModule(
"Align");
2154 int index = addModuleTab(EkosModule::Align, alignModule(),
QIcon(
":/icons/ekos_align.png"));
2155 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Align"));
2156 connect(alignModule(), &Ekos::Align::newLog,
this, &Ekos::Manager::updateLog);
2157 connect(alignModule(), &Ekos::Align::newLog,
this, [
this]()
2161 {
"log", alignModule()->getLogText()}
2164 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2166 if (Options::ekosLeftIcons())
2170 QIcon icon = toolsWidget->tabIcon(index);
2173 toolsWidget->setTabIcon(index, icon);
2179void Manager::initFocus()
2181 if (focusModule() !=
nullptr)
2184 focusProcess.reset(
new Ekos::FocusModule());
2186 emit newModule(
"Focus");
2188 int index = addModuleTab(EkosModule::Focus, focusModule(),
QIcon(
":/icons/ekos_focus.png"));
2190 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2193 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2194 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStarPixmap, focusProgressWidget,
2195 &Ekos::FocusProgressWidget::updateFocusStarPixmap);
2196 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2198 connect(focusModule(), &Ekos::FocusModule::newLog,
this, [
this]()
2205 {
"log", focusModule()->getLogText()}
2208 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2210 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2214 {
"focusAdvisorMessage", message}
2217 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2219 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorStage, ekosLiveClient.get()->message(),
2222 QJsonObject cStatus =
2224 {
"focusAdvisorStage", stage}
2227 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2236 focusProgressWidget->hfrVPlot->init(str, starUnits, minimum, useWeights, showPosition);
2239 {
"focusinitHFRPlot",
true}
2242 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2248 focusProgressWidget->hfrVPlot->setTitle(title, plot);
2254 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2257 &FocusHFRVPlot::setTitle);
2259 &FocusHFRVPlot::redraw);
2261 &FocusHFRVPlot::addPosition);
2263 &FocusHFRVPlot::drawPolynomial);
2265 &FocusHFRVPlot::finalUpdates);
2267 &FocusHFRVPlot::drawMinimum);
2270 &FocusHFRVPlot::drawCurve);
2273 if (Options::ekosLeftIcons())
2277 QIcon icon = toolsWidget->tabIcon(index);
2280 toolsWidget->setTabIcon(index, icon);
2283 focusProgressWidget->init();
2284 focusProgressWidget->setEnabled(
true);
2286 for (
auto &oneDevice : INDIListener::devices())
2288 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2289 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2290 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2291 if (prop1 || prop2 || prop3)
2292 focusModule()->addTemperatureSource(oneDevice);
2298void Manager::updateCurrentHFR(
double newHFR,
int position,
bool inAutofocus)
2300 Q_UNUSED(inAutofocus);
2301 focusProgressWidget->updateCurrentHFR(newHFR);
2309 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2312void Manager::updateSigmas(
double ra,
double de)
2314 guideManager->updateSigmas(ra, de);
2316 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2318 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2321void Manager::initMount()
2323 if (mountModule() !=
nullptr)
2329 if (captureModule() !=
nullptr)
2330 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2332 emit newModule(
"Mount");
2334 int index = addModuleTab(EkosModule::Mount, mountModule(),
QIcon(
":/icons/ekos_mount.png"));
2336 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2337 connect(mountModule(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2344 connect(mountModule(), &Ekos::Mount::pierSideChanged,
this, [&](ISD::Mount::PierSide side)
2346 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"pierSide", side}}));
2348 connect(mountModule()->getMeridianFlipState().
get(),
2349 &Ekos::MeridianFlipState::newMountMFStatus, [&](MeridianFlipState::MeridianFlipMountState status)
2351 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2353 {
"meridianFlipStatus",
status},
2356 connect(mountModule()->getMeridianFlipState().
get(),
2357 &Ekos::MeridianFlipState::newMeridianFlipMountStatusText, [&](
const QString & text)
2360 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2362 {
"meridianFlipText", text},
2363 }), mountModule()->getMeridianFlipState()->getMeridianFlipMountState() == MeridianFlipState::MOUNT_FLIP_NONE);
2364 meridianFlipStatusWidget->setStatus(text);
2366 connect(mountModule(), &Ekos::Mount::autoParkCountdownUpdated,
this, [&](
const QString & text)
2368 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"autoParkCountdown", text}}),
true);
2371 connect(mountModule(), &Ekos::Mount::trainChanged, ekosLiveClient.get()->message(),
2374 connect(mountModule(), &Ekos::Mount::slewRateChanged,
this, [&](
int slewRate)
2377 ekosLiveClient.get()->message()->updateMountStatus(status);
2380 if (Options::ekosLeftIcons())
2384 QIcon icon = toolsWidget->tabIcon(index);
2387 toolsWidget->setTabIcon(index, icon);
2390 mountGroup->setEnabled(
true);
2391 capturePreview->shareMountModule(mountModule());
2396void Manager::initGuide()
2398 if (guideModule() ==
nullptr)
2402 emit newModule(
"Guide");
2405 if (toolsWidget->indexOf(guideModule()) == -1)
2410 int index = addModuleTab(EkosModule::Guide, guideModule(),
QIcon(
":/icons/ekos_guide.png"));
2411 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2412 connect(guideModule(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2413 connect(guideModule(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2415 guideManager->setEnabled(
true);
2417 connect(guideModule(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2418 connect(guideModule(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2419 connect(guideModule(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2420 connect(guideModule(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2423 ekosLiveClient.get()->message()->updateGuideStatus(status);
2425 connect(guideModule(), &Ekos::Guide::newLog, ekosLiveClient.get()->message(),
2428 QJsonObject cStatus =
2430 {
"log", guideModule()->getLogText()}
2433 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2436 if (Options::ekosLeftIcons())
2440 QIcon icon = toolsWidget->tabIcon(index);
2443 toolsWidget->setTabIcon(index, icon);
2445 guideManager->init(guideModule());
2451void Manager::initObservatory()
2453 if (observatoryProcess.get() ==
nullptr)
2456 observatoryProcess.reset(
new Ekos::Observatory());
2458 emit newModule(
"Observatory");
2460 int index = addModuleTab(EkosModule::Observatory, observatoryProcess.get(),
QIcon(
":/icons/ekos_observatory.png"));
2461 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Observatory"));
2462 connect(observatoryProcess.get(), &Ekos::Observatory::newLog,
this, &Ekos::Manager::updateLog);
2464 if (Options::ekosLeftIcons())
2468 QIcon icon = toolsWidget->tabIcon(index);
2471 toolsWidget->setTabIcon(index, icon);
2476void Manager::addGuider(ISD::Guider * device)
2478 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2481void Manager::removeTabs()
2485 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2486 toolsWidget->removeTab(i);
2488 alignProcess.reset();
2489 captureProcess.reset();
2490 focusProcess.reset();
2491 guideProcess.reset();
2492 mountProcess.reset();
2493 observatoryProcess.reset();
2498bool Manager::isRunning(
const QString &process)
2505 return output.
length() > 0;
2510 <<
"-C" << process);
2517void Manager::addObjectToScheduler(
SkyObject *
object)
2519 if (schedulerModule() !=
nullptr)
2520 schedulerModule()->addObject(
object);
2523QString Manager::getCurrentJobName()
2525 return schedulerModule()->getCurrentJobName();
2528bool Manager::setProfile(
const QString &profileName)
2530 int index = profileCombo->findText(profileName);
2535 profileCombo->setCurrentIndex(index);
2540void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2542 ProfileEditor editor(
this);
2543 setProfile(profileInfo[
"name"].
toString());
2544 if (getCurrentProfile(m_CurrentProfile))
2546 editor.setPi(m_CurrentProfile);
2547 editor.setSettings(profileInfo);
2548 editor.saveProfile();
2552void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2554 ProfileEditor editor(
this);
2556 editor.setSettings(profileInfo);
2557 editor.saveProfile();
2560 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2561 getCurrentProfile(m_CurrentProfile);
2564void Manager::deleteNamedProfile(
const QString &name)
2566 if (!getCurrentProfile(m_CurrentProfile))
2569 for (
auto &pi : profiles)
2573 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == m_CurrentProfile && ekosStatus() != Idle))
2576 KStarsData::Instance()->
userdb()->PurgeProfile(pi);
2579 getCurrentProfile(m_CurrentProfile);
2589 for (
auto &pi : profiles)
2591 if (name == pi->name)
2592 return pi->toJson();
2602 for (
int i = 0; i < profileCombo->count(); i++)
2603 profiles << profileCombo->itemText(i);
2608void Manager::addProfile()
2610 ProfileEditor editor(
this);
2616 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2619 getCurrentProfile(m_CurrentProfile);
2622void Manager::editProfile()
2624 ProfileEditor editor(
this);
2626 if (getCurrentProfile(m_CurrentProfile))
2629 editor.setPi(m_CurrentProfile);
2633 int currentIndex = profileCombo->currentIndex();
2637 profileCombo->setCurrentIndex(currentIndex);
2640 getCurrentProfile(m_CurrentProfile);
2644void Manager::deleteProfile()
2646 if (!getCurrentProfile(m_CurrentProfile))
2649 if (m_CurrentProfile->name ==
"Simulators")
2652 auto executeDeleteProfile = [&]()
2654 KStarsData::Instance()->
userdb()->PurgeProfile(m_CurrentProfile);
2657 getCurrentProfile(m_CurrentProfile);
2664 executeDeleteProfile();
2667 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2668 i18n(
"Confirm Delete"));
2672void Manager::wizardProfile()
2678 ProfileEditor editor(
this);
2680 editor.setProfileName(wz.profileName);
2681 editor.setAuxDrivers(wz.selectedAuxDrivers());
2682 if (wz.useInternalServer ==
false)
2683 editor.setHostPort(wz.host, wz.port);
2684 editor.setWebManager(wz.useWebManager);
2685 editor.setGuiderType(wz.selectedExternalGuider());
2687 editor.setConnectionOptionsEnabled(
false);
2693 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2696 getCurrentProfile(m_CurrentProfile);
2702 for (
auto &pi : profiles)
2704 if (profileCombo->currentText() == pi->name)
2716 if (profile->city.isEmpty() ==
false)
2720 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2722 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2727void Manager::updateMountStatus(ISD::Mount::Status status)
2729 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2731 if (status == lastStatus)
2736 mountStatus->setMountState(mountModule()->statusString(), status);
2737 mountStatus->setStyleSheet(
QString());
2741 {
"status", mountModule()->statusString(
false)}
2744 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2747void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2766 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2771 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), trainname);
2780 m_CountdownTimer.stop();
2783 m_CountdownTimer.start();
2792 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2793 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2794 {
"train", trainname}
2797 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2803 capturePreview->updateJobProgress(job, data, trainname);
2807 {
"seqv", job->getCompleted()},
2808 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).
toInt()},
2809 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2812 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2814 if (data && job->getStatus() == JOB_BUSY)
2818 if (Options::useFITSViewer() ==
false)
2819 ekosLiveClient.get()->media()->sendData(data, data->objectName());
2821 if (job->jobType() != SequenceJob::JOBTYPE_PREVIEW)
2822 ekosLiveClient.get()->cloud()->sendData(data, data->objectName());
2826void Manager::updateExposureProgress(Ekos::SequenceJob * job,
const QString &trainname)
2830 {
"expv", job->getExposeLeft()},
2831 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).
toDouble()},
2832 {
"train", trainname}
2835 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2838void Manager::updateCaptureCountDown()
2840 capturePreview->updateCaptureCountDown(-1);
2844 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2845 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2846 {
"ovp", capturePreview->captureCountsWidget->gr_overallProgressBar->value()},
2847 {
"ovl", capturePreview->captureCountsWidget->gr_overallLabel->text()}
2850 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2854void Manager::updateFocusStatus(Ekos::FocusState status)
2856 focusProgressWidget->updateFocusStatus(status);
2860 {
"status", getFocusStatusString(status,
false)}
2863 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2866void Manager::updateGuideStatus(Ekos::GuideState status)
2868 guideManager->updateGuideStatus(status);
2871 {
"status", getGuideStatusString(status,
false)}
2874 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2877void Manager::setTarget(
const QString &name)
2879 capturePreview->targetLabel->setVisible(!
name.
isEmpty());
2880 capturePreview->mountTarget->setVisible(!
name.
isEmpty());
2881 capturePreview->mountTarget->setText(name);
2882 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"target",
name}}));
2885 mountModule()->setTargetName(name);
2888void Manager::showEkosOptions()
2890 QWidget * currentWidget = toolsWidget->currentWidget();
2892 if (alignModule() && alignModule() == currentWidget)
2897 alignSettings->setEnabled(
true);
2898 alignSettings->show();
2903 if (guideModule() && guideModule() == currentWidget)
2909 if (focusModule() && focusModule() == currentWidget)
2914 focusSettings->show();
2915 focusSettings->raise();
2920 const bool isCapture = (captureModule() && captureModule() == currentWidget);
2921 const bool isScheduler = (schedulerModule() && schedulerModule() == currentWidget);
2922 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
2923 if (isCapture || isScheduler || isAnalyze)
2928 if (isScheduler) index = 1;
2929 else if (isCapture) index = 2;
2930 else if (isAnalyze) index = 3;
2931 opsEkos->setCurrentIndex(index);
2936 cDialog->setCurrentPage(ekosOptionsWidget);
2939 cDialog->activateWindow();
2944 if (ekosOptionsWidget ==
nullptr)
2953 cDialog->setCurrentPage(ekosOptionsWidget);
2956 cDialog->activateWindow();
2961void Manager::updateDebugInterfaces()
2965 for (
auto &device : INDIListener::devices())
2967 auto debugProp = device->getProperty(
"DEBUG");
2971 auto debugSP = debugProp.getSwitch();
2974 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2975 debugSP->sp[0].s != ISS_ON)
2977 debugSP->at(0)->setState(ISS_ON);
2978 debugSP->at(1)->setState(ISS_OFF);
2980 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
2982 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2983 debugSP->sp[0].s != ISS_OFF)
2985 debugSP->at(0)->setState(ISS_OFF);
2986 debugSP->at(1)->setState(ISS_ON);
2988 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
2991 if (opsLogs->isINDISettingsChanged())
2992 device->setConfig(SAVE_CONFIG);
2996void Manager::watchDebugProperty(INDI::Property prop)
2998 if (prop.isNameMatch(
"DEBUG"))
3000 auto svp = prop.getSwitch();
3005 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3010 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3011 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3013 svp->sp[0].s = ISS_ON;
3014 svp->sp[1].s = ISS_OFF;
3015 deviceInterface->sendNewProperty(svp);
3016 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3022 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3023 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3025 svp->sp[0].s = ISS_OFF;
3026 svp->sp[1].s = ISS_ON;
3027 deviceInterface->sendNewProperty(svp);
3028 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3033void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3035 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3038void Manager::connectModules()
3041 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3043 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3045 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3047 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3051 if (captureProcess && guideProcess)
3057 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3072 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3078 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3083 if (guideProcess && mountProcess)
3094 if (guideProcess && focusProcess)
3104 if (captureProcess && focusProcess)
3107 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3111 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3115 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3126 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3137 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3141 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3145 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3150 if (captureProcess && alignProcess)
3153 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3156 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3159 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3164 if (captureProcess && mountProcess)
3168 captureModule()->registerNewModule(
"Mount");
3169 mountModule()->registerNewModule(
"Capture");
3185 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3187 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3192 if (captureProcess && ekosLiveClient)
3196 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3198 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3200 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3202 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3204 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3209 if (focusProcess && alignProcess)
3211 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3216 if (focusProcess && mountProcess)
3223 if (mountProcess && alignProcess)
3236 if (mountProcess && guideProcess)
3238 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3243 if (alignProcess && ekosLiveClient)
3248 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3250 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3252 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3253 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3255 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3256 ekosLiveClient.get()->message(),
3258 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3259 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3261 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3262 ekosLiveClient.get()->message(),
3264 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3265 ekosLiveClient.get()->message(),
3267 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3268 ekosLiveClient.get()->media(),
3271 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3273 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3276 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3279 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3282 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3287 if (focusProcess && ekosLiveClient)
3289 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3292 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3293 &EkosLive::Media::sendModuleFrame,
3296 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3297 &EkosLive::Message::sendTrainProfiles,
3300 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3305 if (guideProcess && ekosLiveClient)
3307 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3310 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3313 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3321 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3323 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3325 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3331 connect(captureModule(), &Ekos::Capture::captureComplete,
3333 connect(captureModule(), &Ekos::Capture::captureStarting,
3335 connect(captureModule(), &Ekos::Capture::captureAborted,
3339 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3341 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3349 connect(guideModule(), &Ekos::Guide::newStatus,
3352 connect(guideModule(), &Ekos::Guide::guideStats,
3359 if (focusProcess && analyzeProcess)
3361 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3365 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3367 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3369 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3374 if (alignProcess && analyzeProcess)
3376 connect(alignModule(), &Ekos::Align::newStatus,
3382 if (mountProcess && analyzeProcess)
3388 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3393void Manager::setEkosLiveConnected(
bool enabled)
3395 ekosLiveClient.get()->setConnected(enabled);
3398void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3400 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3403void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3405 ekosLiveClient.get()->setUser(username, password);
3408bool Manager::ekosLiveStatus()
3410 return ekosLiveClient.get()->isConnected();
3416 if (!primaryDriver || !secondaryDriver)
3419 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3420 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3423void Manager::restartDriver(
const QString &deviceName)
3425 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3428 for (
auto &oneDevice : INDIListener::devices())
3430 if (oneDevice->getDeviceName() == deviceName)
3432 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3438 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3441void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3444 if (name ==
"LOGGING")
3446 Options::setDisableLogging(!enabled);
3450 else if (name ==
"FILE")
3452 Options::setLogToFile(enabled);
3456 else if (name ==
"DEFAULT")
3458 Options::setLogToDefault(enabled);
3463 else if (name ==
"VERBOSE")
3465 Options::setVerboseLogging(enabled);
3469 else if (name ==
"INDI")
3471 Options::setINDILogging(enabled);
3474 else if (name ==
"FITS")
3476 Options::setFITSLogging(enabled);
3479 else if (name ==
"CAPTURE")
3481 Options::setCaptureLogging(enabled);
3482 Options::setINDICCDLogging(enabled);
3483 Options::setINDIFilterWheelLogging(enabled);
3486 else if (name ==
"FOCUS")
3488 Options::setFocusLogging(enabled);
3489 Options::setINDIFocuserLogging(enabled);
3492 else if (name ==
"GUIDE")
3494 Options::setGuideLogging(enabled);
3495 Options::setINDICCDLogging(enabled);
3498 else if (name ==
"ALIGNMENT")
3500 Options::setAlignmentLogging(enabled);
3503 else if (name ==
"MOUNT")
3505 Options::setMountLogging(enabled);
3506 Options::setINDIMountLogging(enabled);
3509 else if (name ==
"SCHEDULER")
3511 Options::setSchedulerLogging(enabled);
3514 else if (name ==
"OBSERVATORY")
3516 Options::setObservatoryLogging(enabled);
3521void Manager::acceptPortSelection()
3524 m_PortSelector->accept();
3527void Manager::setPortSelectionComplete()
3529 if (m_CurrentProfile->portSelector)
3532 m_CurrentProfile->portSelector =
false;
3533 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3536 if (m_CurrentProfile->autoConnect)
3540void Manager::activateModule(
const QString &name,
bool popup)
3542 auto child = toolsWidget->findChild<
QWidget *>(
name);
3545 toolsWidget->setCurrentWidget(child);
3557 if (device->isConnected())
3559 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3566 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3572 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3574 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3581 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3586 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3592 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3597 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3601 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3605 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3612void Manager::setDeviceReady()
3616 if (isINDIReady() ==
false)
3622 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3625 if (m_CurrentProfile->portSelector)
3631 if (!m_PortSelector)
3632 m_PortSelectorTimer.start();
3636 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3641 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3644 if (m_ekosStatus != Ekos::Success)
3649 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3651 for (
auto &device : INDIListener::devices())
3652 syncGenericDevice(device);
3653 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3657void Manager::createFilterManager(ISD::FilterWheel *device)
3659 auto name = device->getDeviceName();
3660 if (m_FilterManagers.contains(name) ==
false)
3663 newFM->setFilterWheel(device);
3664 m_FilterManagers[
name] = newFM;
3667 m_FilterManagers[
name]->setFilterWheel(device);
3673 if (m_FilterManagers.contains(name))
3675 fm = m_FilterManagers[
name];
3683 if (m_FilterManagers.size() > 0)
3685 fm = m_FilterManagers.values()[0];
3691void Manager::createRotatorController(
ISD::Rotator *device)
3693 auto Name = device->getDeviceName();
3694 if (m_RotatorControllers.contains(Name) ==
false)
3698 m_RotatorControllers[Name] = newRC;
3704 if (m_RotatorControllers.contains(Name))
3706 rs = m_RotatorControllers[Name];
3712bool Manager::existRotatorController()
3714 return (!m_RotatorControllers.empty());
3717void Manager::setFITSfromFile(
bool previewFromFile)
3719 if (previewFromFile && !FITSfromFile)
3722 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3723 FITSfromFile = previewFromFile;
3724 appendLogText(
i18n(
"Preview source set to external"));
3726 else if (!previewFromFile && FITSfromFile)
3729 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3730 FITSfromFile = previewFromFile;
3731 appendLogText(
i18n(
"Preview source reset to internal"));
3735void Manager::previewFile(
QString filePath)
3737 capturePreview->updateJobPreview(filePath);
3738 appendLogText(
i18n(
"Received external preview file"));
DriverInfo holds all metadata associated with a particular INDI driver.
Align class handles plate-solving and polar alignment measurement and correction using astrometry....
Analysis tab for Ekos sessions.
void setHFR(double newHFR, int position, bool inAutofocus, const QString &trainname)
setHFR Receive the measured HFR value of the latest frame
void updateTargetDistance(double targetDiff)
Slot receiving the update of the current target distance.
void inSequenceAFRequested(bool requested, const QString &trainname)
inSequenceAFRequested Focuser informs that the user wishes an AF run as soon as possible.
void setFocusStatus(FocusState newstate, const QString &trainname)
setFocusStatus Forward the new focus state to the capture module state machine
void setFocusTemperatureDelta(double focusTemperatureDelta, double absTemperature, const QString &trainname)
setFocusTemperatureDelta update the focuser's temperature delta
void setGuideDeviation(double delta_ra, double delta_dec)
setGuideDeviation Set the guiding deviation as measured by the guiding module.
void focusAdaptiveComplete(bool success, const QString &trainname)
focusAdaptiveComplete Forward the new focus state to the capture module state machine
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 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 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 dither()
DBUS interface function.
void resetNonGuidedDither()
Reset non guided dithering properties and initialize the random generator seed if not already done.
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.
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())
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()
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.
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.
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)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString name(StandardAction id)
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)
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
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
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 trimmed() const const
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