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)
2898 alignSettings->
show();
2903 if (guideModule() && guideModule() == currentWidget)
2909 if (focusModule() && focusModule() == currentWidget)
2914 focusSettings->
show();
2915 focusSettings->
raise();
2920 if (schedulerModule() == currentWidget)
2932 if(captureModule() == currentWidget)
2944 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
2950 if (isAnalyze) index = 1;
2951 opsEkos->setCurrentIndex(index);
2964 if (ekosOptionsWidget ==
nullptr)
2981void Manager::updateDebugInterfaces()
2985 for (
auto &device : INDIListener::devices())
2987 auto debugProp = device->getProperty(
"DEBUG");
2991 auto debugSP = debugProp.getSwitch();
2994 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2995 debugSP->sp[0].s != ISS_ON)
2997 debugSP->at(0)->setState(ISS_ON);
2998 debugSP->at(1)->setState(ISS_OFF);
3000 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
3002 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3003 debugSP->sp[0].s != ISS_OFF)
3005 debugSP->at(0)->setState(ISS_OFF);
3006 debugSP->at(1)->setState(ISS_ON);
3008 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
3011 if (opsLogs->isINDISettingsChanged())
3012 device->setConfig(SAVE_CONFIG);
3016void Manager::watchDebugProperty(INDI::Property prop)
3018 if (prop.isNameMatch(
"DEBUG"))
3020 auto svp = prop.getSwitch();
3025 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3030 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3031 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3033 svp->sp[0].s = ISS_ON;
3034 svp->sp[1].s = ISS_OFF;
3035 deviceInterface->sendNewProperty(svp);
3036 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3042 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3043 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3045 svp->sp[0].s = ISS_OFF;
3046 svp->sp[1].s = ISS_ON;
3047 deviceInterface->sendNewProperty(svp);
3048 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3053void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3055 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3058void Manager::connectModules()
3061 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3063 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3065 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3067 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3071 if (captureProcess && guideProcess)
3077 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3092 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3098 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3103 if (guideProcess && mountProcess)
3114 if (guideProcess && focusProcess)
3124 if (captureProcess && focusProcess)
3127 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3131 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3135 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3146 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3157 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3161 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3165 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3170 if (captureProcess && alignProcess)
3173 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3176 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3179 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3184 if (captureProcess && mountProcess)
3188 captureModule()->registerNewModule(
"Mount");
3189 mountModule()->registerNewModule(
"Capture");
3205 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3207 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3212 if (captureProcess && ekosLiveClient)
3216 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3218 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3220 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3222 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3224 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3229 if (focusProcess && alignProcess)
3231 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3236 if (focusProcess && mountProcess)
3243 if (mountProcess && alignProcess)
3256 if (mountProcess && guideProcess)
3258 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3263 if (alignProcess && ekosLiveClient)
3268 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3270 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3272 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3273 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3275 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3276 ekosLiveClient.get()->message(),
3278 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3279 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3281 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3282 ekosLiveClient.get()->message(),
3284 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3285 ekosLiveClient.get()->message(),
3287 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3288 ekosLiveClient.get()->media(),
3291 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3293 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3296 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3299 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3302 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3307 if (focusProcess && ekosLiveClient)
3309 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3312 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3313 &EkosLive::Media::sendModuleFrame,
3316 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3317 &EkosLive::Message::sendTrainProfiles,
3320 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3325 if (guideProcess && ekosLiveClient)
3327 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3330 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3333 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3341 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3343 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3345 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3351 connect(captureModule(), &Ekos::Capture::captureComplete,
3353 connect(captureModule(), &Ekos::Capture::captureStarting,
3355 connect(captureModule(), &Ekos::Capture::captureAborted,
3359 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3361 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3369 connect(guideModule(), &Ekos::Guide::newStatus,
3372 connect(guideModule(), &Ekos::Guide::guideStats,
3379 if (focusProcess && analyzeProcess)
3381 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3385 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3387 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3389 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3394 if (alignProcess && analyzeProcess)
3396 connect(alignModule(), &Ekos::Align::newStatus,
3402 if (mountProcess && analyzeProcess)
3408 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3413void Manager::setEkosLiveConnected(
bool enabled)
3415 ekosLiveClient.get()->setConnected(enabled);
3418void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3420 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3423void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3425 ekosLiveClient.get()->setUser(username, password);
3428bool Manager::ekosLiveStatus()
3430 return ekosLiveClient.get()->isConnected();
3436 if (!primaryDriver || !secondaryDriver)
3439 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3440 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3443void Manager::restartDriver(
const QString &deviceName)
3445 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3448 for (
auto &oneDevice : INDIListener::devices())
3450 if (oneDevice->getDeviceName() == deviceName)
3452 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3458 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3461void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3464 if (name ==
"LOGGING")
3466 Options::setDisableLogging(!enabled);
3470 else if (name ==
"FILE")
3472 Options::setLogToFile(enabled);
3476 else if (name ==
"DEFAULT")
3478 Options::setLogToDefault(enabled);
3483 else if (name ==
"VERBOSE")
3485 Options::setVerboseLogging(enabled);
3489 else if (name ==
"INDI")
3491 Options::setINDILogging(enabled);
3494 else if (name ==
"FITS")
3496 Options::setFITSLogging(enabled);
3499 else if (name ==
"CAPTURE")
3501 Options::setCaptureLogging(enabled);
3502 Options::setINDICCDLogging(enabled);
3503 Options::setINDIFilterWheelLogging(enabled);
3506 else if (name ==
"FOCUS")
3508 Options::setFocusLogging(enabled);
3509 Options::setINDIFocuserLogging(enabled);
3512 else if (name ==
"GUIDE")
3514 Options::setGuideLogging(enabled);
3515 Options::setINDICCDLogging(enabled);
3518 else if (name ==
"ALIGNMENT")
3520 Options::setAlignmentLogging(enabled);
3523 else if (name ==
"MOUNT")
3525 Options::setMountLogging(enabled);
3526 Options::setINDIMountLogging(enabled);
3529 else if (name ==
"SCHEDULER")
3531 Options::setSchedulerLogging(enabled);
3534 else if (name ==
"OBSERVATORY")
3536 Options::setObservatoryLogging(enabled);
3541void Manager::acceptPortSelection()
3544 m_PortSelector->accept();
3547void Manager::setPortSelectionComplete()
3549 if (m_CurrentProfile->portSelector)
3552 m_CurrentProfile->portSelector =
false;
3553 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3556 if (m_CurrentProfile->autoConnect)
3560void Manager::activateModule(
const QString &name,
bool popup)
3562 auto child = toolsWidget->findChild<
QWidget *>(
name);
3565 toolsWidget->setCurrentWidget(child);
3577 if (device->isConnected())
3579 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3586 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3592 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3594 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3601 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3606 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3612 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3617 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3621 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3625 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3632void Manager::setDeviceReady()
3636 if (isINDIReady() ==
false)
3642 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3645 if (m_CurrentProfile->portSelector)
3651 if (!m_PortSelector)
3652 m_PortSelectorTimer.start();
3656 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3661 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3664 if (m_ekosStatus != Ekos::Success)
3669 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3671 for (
auto &device : INDIListener::devices())
3672 syncGenericDevice(device);
3673 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3677void Manager::createFilterManager(ISD::FilterWheel *device)
3679 auto name = device->getDeviceName();
3680 if (m_FilterManagers.contains(name) ==
false)
3683 newFM->setFilterWheel(device);
3684 m_FilterManagers[
name] = newFM;
3687 m_FilterManagers[
name]->setFilterWheel(device);
3693 if (m_FilterManagers.contains(name))
3695 fm = m_FilterManagers[
name];
3703 if (m_FilterManagers.size() > 0)
3705 fm = m_FilterManagers.values()[0];
3711void Manager::createRotatorController(
ISD::Rotator *device)
3713 auto Name = device->getDeviceName();
3714 if (m_RotatorControllers.contains(Name) ==
false)
3718 m_RotatorControllers[Name] = newRC;
3724 if (m_RotatorControllers.contains(Name))
3726 rs = m_RotatorControllers[Name];
3732bool Manager::existRotatorController()
3734 return (!m_RotatorControllers.empty());
3737void Manager::setFITSfromFile(
bool previewFromFile)
3739 if (previewFromFile && !FITSfromFile)
3742 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3743 FITSfromFile = previewFromFile;
3744 appendLogText(
i18n(
"Preview source set to external"));
3746 else if (!previewFromFile && FITSfromFile)
3749 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3750 FITSfromFile = previewFromFile;
3751 appendLogText(
i18n(
"Preview source reset to internal"));
3755void Manager::previewFile(
QString filePath)
3757 capturePreview->updateJobPreview(filePath);
3758 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 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.
QString name(GameStandardAction id)
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
GeoCoordinates geo(const QVariant &location)
QVariant location(const QVariant &res)
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 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