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 connect(alignModule(), &Ekos::Align::newDownloadProgress,
this, [
this](
QString info)
2170 {
"downloadProgress", info}
2173 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2175 if (Options::ekosLeftIcons())
2179 QIcon icon = toolsWidget->tabIcon(index);
2182 toolsWidget->setTabIcon(index, icon);
2188void Manager::initFocus()
2190 if (focusModule() !=
nullptr)
2193 focusProcess.reset(
new Ekos::FocusModule());
2195 emit newModule(
"Focus");
2197 int index = addModuleTab(EkosModule::Focus, focusModule(),
QIcon(
":/icons/ekos_focus.png"));
2199 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2202 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2203 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStarPixmap, focusProgressWidget,
2204 &Ekos::FocusProgressWidget::updateFocusStarPixmap);
2205 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2207 connect(focusModule(), &Ekos::FocusModule::newLog,
this, [
this]()
2214 {
"log", focusModule()->getLogText()}
2217 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2219 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2223 {
"focusAdvisorMessage", message}
2226 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2228 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorStage, ekosLiveClient.get()->message(),
2231 QJsonObject cStatus =
2233 {
"focusAdvisorStage", stage}
2236 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2245 focusProgressWidget->hfrVPlot->init(str, starUnits, minimum, useWeights, showPosition);
2248 {
"focusinitHFRPlot",
true}
2251 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2257 focusProgressWidget->hfrVPlot->setTitle(title, plot);
2263 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2266 &FocusHFRVPlot::setTitle);
2268 &FocusHFRVPlot::redraw);
2270 &FocusHFRVPlot::addPosition);
2272 &FocusHFRVPlot::drawPolynomial);
2274 &FocusHFRVPlot::finalUpdates);
2276 &FocusHFRVPlot::drawMinimum);
2279 &FocusHFRVPlot::drawCurve);
2282 if (Options::ekosLeftIcons())
2286 QIcon icon = toolsWidget->tabIcon(index);
2289 toolsWidget->setTabIcon(index, icon);
2292 focusProgressWidget->init();
2293 focusProgressWidget->setEnabled(
true);
2295 for (
auto &oneDevice : INDIListener::devices())
2297 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2298 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2299 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2300 if (prop1 || prop2 || prop3)
2301 focusModule()->addTemperatureSource(oneDevice);
2307void Manager::updateCurrentHFR(
double newHFR,
int position,
bool inAutofocus)
2309 Q_UNUSED(inAutofocus);
2310 focusProgressWidget->updateCurrentHFR(newHFR);
2318 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2321void Manager::updateSigmas(
double ra,
double de)
2323 guideManager->updateSigmas(ra, de);
2325 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2327 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2330void Manager::initMount()
2332 if (mountModule() !=
nullptr)
2338 if (captureModule() !=
nullptr)
2339 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2341 emit newModule(
"Mount");
2343 int index = addModuleTab(EkosModule::Mount, mountModule(),
QIcon(
":/icons/ekos_mount.png"));
2345 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2346 connect(mountModule(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2353 connect(mountModule(), &Ekos::Mount::pierSideChanged,
this, [&](ISD::Mount::PierSide side)
2355 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"pierSide", side}}));
2357 connect(mountModule()->getMeridianFlipState().
get(),
2358 &Ekos::MeridianFlipState::newMountMFStatus, [&](MeridianFlipState::MeridianFlipMountState status)
2360 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2362 {
"meridianFlipStatus",
status},
2365 connect(mountModule()->getMeridianFlipState().
get(),
2366 &Ekos::MeridianFlipState::newMeridianFlipMountStatusText, [&](
const QString & text)
2369 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject(
2371 {
"meridianFlipText", text},
2372 }), mountModule()->getMeridianFlipState()->getMeridianFlipMountState() == MeridianFlipState::MOUNT_FLIP_NONE);
2373 meridianFlipStatusWidget->setStatus(text);
2375 connect(mountModule(), &Ekos::Mount::autoParkCountdownUpdated,
this, [&](
const QString & text)
2377 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"autoParkCountdown", text}}),
true);
2380 connect(mountModule(), &Ekos::Mount::trainChanged, ekosLiveClient.get()->message(),
2383 connect(mountModule(), &Ekos::Mount::slewRateChanged,
this, [&](
int slewRate)
2386 ekosLiveClient.get()->message()->updateMountStatus(status);
2389 if (Options::ekosLeftIcons())
2393 QIcon icon = toolsWidget->tabIcon(index);
2396 toolsWidget->setTabIcon(index, icon);
2399 mountGroup->setEnabled(
true);
2400 capturePreview->shareMountModule(mountModule());
2405void Manager::initGuide()
2407 if (guideModule() ==
nullptr)
2411 emit newModule(
"Guide");
2414 if (toolsWidget->indexOf(guideModule()) == -1)
2419 int index = addModuleTab(EkosModule::Guide, guideModule(),
QIcon(
":/icons/ekos_guide.png"));
2420 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2421 connect(guideModule(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2422 connect(guideModule(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2424 guideManager->setEnabled(
true);
2426 connect(guideModule(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2427 connect(guideModule(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2428 connect(guideModule(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2429 connect(guideModule(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2432 ekosLiveClient.get()->message()->updateGuideStatus(status);
2434 connect(guideModule(), &Ekos::Guide::newLog, ekosLiveClient.get()->message(),
2437 QJsonObject cStatus =
2439 {
"log", guideModule()->getLogText()}
2442 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2445 if (Options::ekosLeftIcons())
2449 QIcon icon = toolsWidget->tabIcon(index);
2452 toolsWidget->setTabIcon(index, icon);
2454 guideManager->init(guideModule());
2460void Manager::initObservatory()
2462 if (observatoryProcess.get() ==
nullptr)
2465 observatoryProcess.reset(
new Ekos::Observatory());
2467 emit newModule(
"Observatory");
2469 int index = addModuleTab(EkosModule::Observatory, observatoryProcess.get(),
QIcon(
":/icons/ekos_observatory.png"));
2470 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Observatory"));
2471 connect(observatoryProcess.get(), &Ekos::Observatory::newLog,
this, &Ekos::Manager::updateLog);
2473 if (Options::ekosLeftIcons())
2477 QIcon icon = toolsWidget->tabIcon(index);
2480 toolsWidget->setTabIcon(index, icon);
2485void Manager::addGuider(ISD::Guider * device)
2487 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2490void Manager::removeTabs()
2494 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2495 toolsWidget->removeTab(i);
2497 alignProcess.reset();
2498 captureProcess.reset();
2499 focusProcess.reset();
2500 guideProcess.reset();
2501 mountProcess.reset();
2502 observatoryProcess.reset();
2507bool Manager::isRunning(
const QString &process)
2514 return output.
length() > 0;
2519 <<
"-C" << process);
2526void Manager::addObjectToScheduler(
SkyObject *
object)
2528 if (schedulerModule() !=
nullptr)
2529 schedulerModule()->addObject(
object);
2532QString Manager::getCurrentJobName()
2534 return schedulerModule()->getCurrentJobName();
2537bool Manager::setProfile(
const QString &profileName)
2539 int index = profileCombo->findText(profileName);
2544 profileCombo->setCurrentIndex(index);
2549void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2551 ProfileEditor editor(
this);
2552 setProfile(profileInfo[
"name"].
toString());
2553 if (getCurrentProfile(m_CurrentProfile))
2555 editor.setPi(m_CurrentProfile);
2556 editor.setSettings(profileInfo);
2557 editor.saveProfile();
2561void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2563 ProfileEditor editor(
this);
2565 editor.setSettings(profileInfo);
2566 editor.saveProfile();
2569 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2570 getCurrentProfile(m_CurrentProfile);
2573void Manager::deleteNamedProfile(
const QString &name)
2575 if (!getCurrentProfile(m_CurrentProfile))
2578 for (
auto &pi : profiles)
2582 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == m_CurrentProfile && ekosStatus() != Idle))
2585 KStarsData::Instance()->
userdb()->PurgeProfile(pi);
2588 getCurrentProfile(m_CurrentProfile);
2598 for (
auto &pi : profiles)
2600 if (name == pi->name)
2601 return pi->toJson();
2611 for (
int i = 0; i < profileCombo->count(); i++)
2612 profiles << profileCombo->itemText(i);
2617void Manager::addProfile()
2619 ProfileEditor editor(
this);
2625 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2628 getCurrentProfile(m_CurrentProfile);
2631void Manager::editProfile()
2633 ProfileEditor editor(
this);
2635 if (getCurrentProfile(m_CurrentProfile))
2638 editor.setPi(m_CurrentProfile);
2642 int currentIndex = profileCombo->currentIndex();
2646 profileCombo->setCurrentIndex(currentIndex);
2649 getCurrentProfile(m_CurrentProfile);
2653void Manager::deleteProfile()
2655 if (!getCurrentProfile(m_CurrentProfile))
2658 if (m_CurrentProfile->name ==
"Simulators")
2661 auto executeDeleteProfile = [&]()
2663 KStarsData::Instance()->
userdb()->PurgeProfile(m_CurrentProfile);
2666 getCurrentProfile(m_CurrentProfile);
2673 executeDeleteProfile();
2676 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2677 i18n(
"Confirm Delete"));
2681void Manager::wizardProfile()
2687 ProfileEditor editor(
this);
2689 editor.setProfileName(wz.profileName);
2690 editor.setAuxDrivers(wz.selectedAuxDrivers());
2691 if (wz.useInternalServer ==
false)
2692 editor.setHostPort(wz.host, wz.port);
2693 editor.setWebManager(wz.useWebManager);
2694 editor.setGuiderType(wz.selectedExternalGuider());
2696 editor.setConnectionOptionsEnabled(
false);
2702 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2705 getCurrentProfile(m_CurrentProfile);
2711 for (
auto &pi : profiles)
2713 if (profileCombo->currentText() == pi->name)
2725 if (profile->city.isEmpty() ==
false)
2729 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2731 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2736void Manager::updateMountStatus(ISD::Mount::Status status)
2738 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2740 if (status == lastStatus)
2745 mountStatus->setMountState(mountModule()->statusString(), status);
2746 mountStatus->setStyleSheet(
QString());
2750 {
"status", mountModule()->statusString(
false)}
2753 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2756void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2759 raOUT->setText(position.
ra().toHMSString());
2760 decOUT->setText(position.
dec().toDMSString());
2761 azOUT->setText(position.
az().toDMSString());
2762 altOUT->setText(position.
alt().toDMSString());
2768 {
"ra0", position.
ra0().Degrees()},
2769 {
"de0", position.
dec0().Degrees()},
2775 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2780 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), trainname);
2789 m_CountdownTimer.stop();
2792 m_CountdownTimer.start();
2801 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2802 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2803 {
"train", trainname}
2806 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2812 capturePreview->updateJobProgress(job, data, trainname);
2816 {
"seqv", job->getCompleted()},
2817 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).
toInt()},
2818 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2821 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2823 if (data && job->getStatus() == JOB_BUSY)
2827 if (Options::useFITSViewer() ==
false)
2828 ekosLiveClient.get()->media()->sendData(data, data->objectName());
2830 if (job->jobType() != SequenceJob::JOBTYPE_PREVIEW)
2831 ekosLiveClient.get()->cloud()->sendData(data, data->objectName());
2835void Manager::updateExposureProgress(Ekos::SequenceJob * job,
const QString &trainname)
2839 {
"expv", job->getExposeLeft()},
2840 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).
toDouble()},
2841 {
"train", trainname}
2844 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2847void Manager::updateCaptureCountDown()
2849 capturePreview->updateCaptureCountDown(-1);
2853 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2854 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2855 {
"ovp", capturePreview->captureCountsWidget->gr_overallProgressBar->value()},
2856 {
"ovl", capturePreview->captureCountsWidget->gr_overallLabel->text()}
2859 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2863void Manager::updateFocusStatus(Ekos::FocusState status)
2865 focusProgressWidget->updateFocusStatus(status);
2869 {
"status", getFocusStatusString(status,
false)}
2872 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2875void Manager::updateGuideStatus(Ekos::GuideState status)
2877 guideManager->updateGuideStatus(status);
2880 {
"status", getGuideStatusString(status,
false)}
2883 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2886void Manager::setTarget(
const QString &name)
2888 capturePreview->targetLabel->setVisible(!
name.
isEmpty());
2889 capturePreview->mountTarget->setVisible(!
name.
isEmpty());
2890 capturePreview->mountTarget->setText(name);
2891 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"target",
name}}));
2894 mountModule()->setTargetName(name);
2897void Manager::showEkosOptions()
2899 QWidget * currentWidget = toolsWidget->currentWidget();
2901 if (alignModule() && alignModule() == currentWidget)
2907 alignSettings->
show();
2912 if (guideModule() && guideModule() == currentWidget)
2918 if (focusModule() && focusModule() == currentWidget)
2923 focusSettings->
show();
2924 focusSettings->
raise();
2929 if (schedulerModule() == currentWidget)
2941 if(captureModule() == currentWidget)
2953 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
2959 if (isAnalyze) index = 1;
2960 opsEkos->setCurrentIndex(index);
2973 if (ekosOptionsWidget ==
nullptr)
2990void Manager::updateDebugInterfaces()
2994 for (
auto &device : INDIListener::devices())
2996 auto debugProp = device->getProperty(
"DEBUG");
3000 auto debugSP = debugProp.getSwitch();
3003 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3004 debugSP->sp[0].s != ISS_ON)
3006 debugSP->at(0)->setState(ISS_ON);
3007 debugSP->at(1)->setState(ISS_OFF);
3009 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
3011 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3012 debugSP->sp[0].s != ISS_OFF)
3014 debugSP->at(0)->setState(ISS_OFF);
3015 debugSP->at(1)->setState(ISS_ON);
3017 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
3020 if (opsLogs->isINDISettingsChanged())
3021 device->setConfig(SAVE_CONFIG);
3025void Manager::watchDebugProperty(INDI::Property prop)
3027 if (prop.isNameMatch(
"DEBUG"))
3029 auto svp = prop.getSwitch();
3034 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3039 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3040 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3042 svp->sp[0].s = ISS_ON;
3043 svp->sp[1].s = ISS_OFF;
3044 deviceInterface->sendNewProperty(svp);
3045 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3051 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3052 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3054 svp->sp[0].s = ISS_OFF;
3055 svp->sp[1].s = ISS_ON;
3056 deviceInterface->sendNewProperty(svp);
3057 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3062void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3064 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3067void Manager::connectModules()
3070 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3072 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3074 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3076 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3080 if (captureProcess && guideProcess)
3086 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3101 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3107 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3112 if (guideProcess && mountProcess)
3123 if (guideProcess && focusProcess)
3133 if (captureProcess && focusProcess)
3136 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3140 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3144 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3155 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3166 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3170 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3174 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3179 if (captureProcess && alignProcess)
3182 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3185 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3188 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3193 if (captureProcess && mountProcess)
3197 captureModule()->registerNewModule(
"Mount");
3198 mountModule()->registerNewModule(
"Capture");
3214 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3216 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3221 if (captureProcess && ekosLiveClient)
3225 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3227 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3229 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3231 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3233 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3238 if (focusProcess && alignProcess)
3240 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3245 if (focusProcess && mountProcess)
3252 if (mountProcess && alignProcess)
3265 if (mountProcess && guideProcess)
3267 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3272 if (alignProcess && ekosLiveClient)
3277 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3279 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3281 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3282 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3284 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3285 ekosLiveClient.get()->message(),
3287 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3288 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3290 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3291 ekosLiveClient.get()->message(),
3293 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3294 ekosLiveClient.get()->message(),
3296 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3297 ekosLiveClient.get()->media(),
3300 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3302 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3305 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3308 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3311 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3316 if (focusProcess && ekosLiveClient)
3318 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3321 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3322 &EkosLive::Media::sendModuleFrame,
3325 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3326 &EkosLive::Message::sendTrainProfiles,
3329 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3334 if (guideProcess && ekosLiveClient)
3336 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3339 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3342 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3350 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3352 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3354 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3360 connect(captureModule(), &Ekos::Capture::captureComplete,
3362 connect(captureModule(), &Ekos::Capture::captureStarting,
3364 connect(captureModule(), &Ekos::Capture::captureAborted,
3368 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3370 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3378 connect(guideModule(), &Ekos::Guide::newStatus,
3381 connect(guideModule(), &Ekos::Guide::guideStats,
3388 if (focusProcess && analyzeProcess)
3390 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3394 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3396 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3398 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3403 if (alignProcess && analyzeProcess)
3405 connect(alignModule(), &Ekos::Align::newStatus,
3411 if (mountProcess && analyzeProcess)
3417 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3422void Manager::setEkosLiveConnected(
bool enabled)
3424 ekosLiveClient.get()->setConnected(enabled);
3427void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3429 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3432void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3434 ekosLiveClient.get()->setUser(username, password);
3437bool Manager::ekosLiveStatus()
3439 return ekosLiveClient.get()->isConnected();
3445 if (!primaryDriver || !secondaryDriver)
3448 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3449 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3452void Manager::restartDriver(
const QString &deviceName)
3454 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3457 for (
auto &oneDevice : INDIListener::devices())
3459 if (oneDevice->getDeviceName() == deviceName)
3461 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3467 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3470void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3473 if (name ==
"LOGGING")
3475 Options::setDisableLogging(!enabled);
3479 else if (name ==
"FILE")
3481 Options::setLogToFile(enabled);
3485 else if (name ==
"DEFAULT")
3487 Options::setLogToDefault(enabled);
3492 else if (name ==
"VERBOSE")
3494 Options::setVerboseLogging(enabled);
3498 else if (name ==
"INDI")
3500 Options::setINDILogging(enabled);
3503 else if (name ==
"FITS")
3505 Options::setFITSLogging(enabled);
3508 else if (name ==
"CAPTURE")
3510 Options::setCaptureLogging(enabled);
3511 Options::setINDICCDLogging(enabled);
3512 Options::setINDIFilterWheelLogging(enabled);
3515 else if (name ==
"FOCUS")
3517 Options::setFocusLogging(enabled);
3518 Options::setINDIFocuserLogging(enabled);
3521 else if (name ==
"GUIDE")
3523 Options::setGuideLogging(enabled);
3524 Options::setINDICCDLogging(enabled);
3527 else if (name ==
"ALIGNMENT")
3529 Options::setAlignmentLogging(enabled);
3532 else if (name ==
"MOUNT")
3534 Options::setMountLogging(enabled);
3535 Options::setINDIMountLogging(enabled);
3538 else if (name ==
"SCHEDULER")
3540 Options::setSchedulerLogging(enabled);
3543 else if (name ==
"OBSERVATORY")
3545 Options::setObservatoryLogging(enabled);
3550void Manager::acceptPortSelection()
3553 m_PortSelector->accept();
3556void Manager::setPortSelectionComplete()
3558 if (m_CurrentProfile->portSelector)
3561 m_CurrentProfile->portSelector =
false;
3562 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3565 if (m_CurrentProfile->autoConnect)
3569void Manager::activateModule(
const QString &name,
bool popup)
3571 auto child = toolsWidget->findChild<
QWidget *>(
name);
3574 toolsWidget->setCurrentWidget(child);
3586 if (device->isConnected())
3588 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3595 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3601 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3603 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3610 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3615 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3621 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3626 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3630 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3634 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3641void Manager::setDeviceReady()
3645 if (isINDIReady() ==
false)
3651 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3654 if (m_CurrentProfile->portSelector)
3660 if (!m_PortSelector)
3661 m_PortSelectorTimer.start();
3665 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3670 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3673 if (m_ekosStatus != Ekos::Success)
3678 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3680 for (
auto &device : INDIListener::devices())
3681 syncGenericDevice(device);
3682 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3686void Manager::createFilterManager(ISD::FilterWheel *device)
3688 auto name = device->getDeviceName();
3689 if (m_FilterManagers.contains(name) ==
false)
3692 newFM->setFilterWheel(device);
3693 m_FilterManagers[
name] = newFM;
3696 m_FilterManagers[
name]->setFilterWheel(device);
3702 if (m_FilterManagers.contains(name))
3704 fm = m_FilterManagers[
name];
3712 if (m_FilterManagers.size() > 0)
3714 fm = m_FilterManagers.values()[0];
3720void Manager::createRotatorController(
ISD::Rotator *device)
3722 auto Name = device->getDeviceName();
3723 if (m_RotatorControllers.contains(Name) ==
false)
3727 m_RotatorControllers[Name] = newRC;
3733 if (m_RotatorControllers.contains(Name))
3735 rs = m_RotatorControllers[Name];
3741bool Manager::existRotatorController()
3743 return (!m_RotatorControllers.empty());
3746void Manager::setFITSfromFile(
bool previewFromFile)
3748 if (previewFromFile && !FITSfromFile)
3751 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3752 FITSfromFile = previewFromFile;
3753 appendLogText(
i18n(
"Preview source set to external"));
3755 else if (!previewFromFile && FITSfromFile)
3758 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3759 FITSfromFile = previewFromFile;
3760 appendLogText(
i18n(
"Preview source reset to internal"));
3764void Manager::previewFile(
QString filePath)
3766 capturePreview->updateJobPreview(filePath);
3767 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())
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()
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 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