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;
75Manager *Manager::Instance()
77 if (_Manager ==
nullptr)
78 _Manager =
new Manager(Options::independentWindowEkos() ?
nullptr :
KStars::Instance());
83void Manager::release()
85 ProfileSettings::release();
86 OpticalTrainManager::release();
87 OpticalTrainSettings::release();
88 RotatorUtils::release();
92Manager::Manager(QWidget * parent) : QDialog(parent)
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)
566 QList<QStandardItem *> info;
568 info <<
new QStandardItem(pi->id) <<
new QStandardItem(pi->name) <<
new QStandardItem(pi->host)
569 <<
new QStandardItem(pi->port);
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);
773 QJsonParseError jsonError;
774 QJsonArray profileScripts;
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];
904 QStringList
location = hostport.split(
':');
915 QSharedPointer<DriverInfo> dv(
new DriverInfo(name));
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();
942 QSharedPointer<DriverInfo> remote_indi(
new DriverInfo(QString(
"Ekos Remote Host")));
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();
969 QList<QSharedPointer<DriverInfo>> sortedList;
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";
1053 QStringList arguments;
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;
1122 QFutureWatcher<bool> *watcher =
new QFutureWatcher<bool>();
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())
1228 indiHubAgent =
new QProcess();
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)
1279 QStringList disconnectedDevices;
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);
1309 QStringList remainingDevices;
1310 for (
auto &drv : managedDrivers)
1312 if (drv->getDevices().count() == 0)
1313 remainingDevices << QString(
"+ %1").arg(
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);
1336 QStringList remainingDevices;
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()
1595 ISD::GenericDevice * dev =
static_cast<ISD::GenericDevice *
>(sender());
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)
1658 QString
name = device->getDeviceName();
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())
1734 QSharedPointer<ISD::GenericDevice>
generic;
1735 if (INDIListener::findDevice(camera->getDeviceName(), generic))
1736 focusModule()->addTemperatureSource(generic);
1745 auto mount = device->getMount();
1750 QSharedPointer<ISD::GenericDevice>
generic;
1751 if (INDIListener::findDevice(
mount->getDeviceName(), generic))
1753 mountModule()->addTimeSource(generic);
1754 mountModule()->addLocationSource(generic);
1763 auto focuser = device->getFocuser();
1769 QSharedPointer<ISD::GenericDevice>
generic;
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);
1808 QSharedPointer<ISD::GenericDevice>
generic;
1809 if (INDIListener::findDevice(weather->getDeviceName(), generic))
1810 focusModule()->addTemperatureSource(generic);
1817 auto gps = device->getGPS();
1822 QSharedPointer<ISD::GenericDevice>
generic;
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)
1881 auto origin =
static_cast<ISD::GenericDevice *
>(sender());
1885 QSharedPointer<ISD::GenericDevice> device;
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)
1916 QSharedPointer<ISD::GenericDevice> device;
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);
2109 QPixmap pix = icon.
pixmap(QSize(48, 48));
2111 toolsWidget->setTabIcon(index, icon);
2113 connect(captureModule(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2114 connect(captureModule(), &Ekos::Capture::newLog,
this, [
this]()
2116 QJsonObject cStatus =
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]()
2159 QJsonObject cStatus =
2161 {
"log", alignModule()->getLogText()}
2164 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2166 connect(alignModule(), &Ekos::Align::newDownloadProgress,
this, [
this](QString info)
2168 QJsonObject cStatus =
2170 {
"downloadProgress", info}
2173 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2175 if (Options::ekosLeftIcons())
2179 QIcon icon = toolsWidget->tabIcon(index);
2180 QPixmap pix = icon.
pixmap(QSize(48, 48));
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]()
2212 QJsonObject cStatus =
2214 {
"log", focusModule()->getLogText()}
2217 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2219 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2221 QJsonObject cStatus =
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);
2312 QJsonObject cStatus =
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)
2335 mountProcess.reset(
new Ekos::Mount());
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)
2385 QJsonObject
status = { {
"slewRate", slewRate} };
2386 ekosLiveClient.get()->message()->updateMountStatus(status);
2389 if (Options::ekosLeftIcons())
2393 QIcon icon = toolsWidget->tabIcon(index);
2394 QPixmap pix = icon.
pixmap(QSize(48, 48));
2396 toolsWidget->setTabIcon(index, icon);
2399 mountGroup->setEnabled(
true);
2400 capturePreview->shareMountModule(mountModule());
2405void Manager::initGuide()
2407 if (guideModule() ==
nullptr)
2409 guideProcess.reset(
new Ekos::Guide());
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)
2431 QJsonObject
status = { {
"drift_ra", ra}, {
"drift_de", 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);
2450 QPixmap pix = icon.
pixmap(QSize(48, 48));
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);
2478 QPixmap pix = icon.
pixmap(QSize(48, 48));
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)
2511 ps.
start(
"pgrep", QStringList() << process);
2514 return output.
length() > 0;
2516 ps.
start(
"ps", QStringList() <<
"-o"
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);
2595 QJsonObject profileInfo;
2598 for (
auto &pi : profiles)
2600 if (name == pi->name)
2601 return pi->toJson();
2604 return QJsonObject();
2609 QStringList profiles;
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());
2748 QJsonObject cStatus =
2750 {
"status", mountModule()->statusString(
false)}
2753 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2756void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2764 QJsonObject cStatus =
2775 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2780 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), trainname);
2789 m_CountdownTimer.stop();
2792 m_CountdownTimer.start();
2798 QJsonObject cStatus =
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);
2867 QJsonObject cStatus =
2869 {
"status", getFocusStatusString(status,
false)}
2872 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2875void Manager::updateGuideStatus(Ekos::GuideState status)
2877 guideManager->updateGuideStatus(status);
2878 QJsonObject cStatus =
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)
2920 focusModule()->showOptions();
2924 if (schedulerModule() == currentWidget)
2936 if(captureModule() == currentWidget)
2948 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
2954 if (isAnalyze) index = 1;
2955 opsEkos->setCurrentIndex(index);
2968 if (ekosOptionsWidget ==
nullptr)
2985void Manager::updateDebugInterfaces()
2989 for (
auto &device : INDIListener::devices())
2991 auto debugProp = device->getProperty(
"DEBUG");
2995 auto debugSP = debugProp.getSwitch();
2998 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2999 debugSP->sp[0].s != ISS_ON)
3001 debugSP->at(0)->setState(ISS_ON);
3002 debugSP->at(1)->setState(ISS_OFF);
3004 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
3006 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3007 debugSP->sp[0].s != ISS_OFF)
3009 debugSP->at(0)->setState(ISS_OFF);
3010 debugSP->at(1)->setState(ISS_ON);
3012 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
3015 if (opsLogs->isINDISettingsChanged())
3016 device->setConfig(SAVE_CONFIG);
3020void Manager::watchDebugProperty(INDI::Property prop)
3022 if (prop.isNameMatch(
"DEBUG"))
3024 auto svp = prop.getSwitch();
3026 ISD::GenericDevice * deviceInterface = qobject_cast<ISD::GenericDevice *>(sender());
3029 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3034 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3035 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3037 svp->sp[0].s = ISS_ON;
3038 svp->sp[1].s = ISS_OFF;
3039 deviceInterface->sendNewProperty(svp);
3040 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3046 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3047 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3049 svp->sp[0].s = ISS_OFF;
3050 svp->sp[1].s = ISS_ON;
3051 deviceInterface->sendNewProperty(svp);
3052 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3057void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3059 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3062void Manager::connectModules()
3065 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3067 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3069 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3071 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3075 if (captureProcess && guideProcess)
3081 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3096 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3102 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3107 if (guideProcess && mountProcess)
3118 if (guideProcess && focusProcess)
3128 if (captureProcess && focusProcess)
3131 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3135 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3139 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3150 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3161 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3165 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3169 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3174 if (captureProcess && alignProcess)
3177 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3180 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3183 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3188 if (captureProcess && mountProcess)
3192 captureModule()->registerNewModule(
"Mount");
3193 mountModule()->registerNewModule(
"Capture");
3209 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3211 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3216 if (captureProcess && ekosLiveClient)
3220 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3222 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3224 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3226 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3228 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3233 if (focusProcess && alignProcess)
3235 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3240 if (focusProcess && mountProcess)
3247 if (mountProcess && alignProcess)
3260 if (mountProcess && guideProcess)
3262 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3267 if (alignProcess && ekosLiveClient)
3272 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3274 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3276 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3277 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3279 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3280 ekosLiveClient.get()->message(),
3282 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3283 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3285 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3286 ekosLiveClient.get()->message(),
3288 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3289 ekosLiveClient.get()->message(),
3291 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3292 ekosLiveClient.get()->media(),
3295 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3297 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3300 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3303 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3306 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3311 if (focusProcess && ekosLiveClient)
3313 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3316 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3317 &EkosLive::Media::sendModuleFrame,
3320 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3321 &EkosLive::Message::sendTrainProfiles,
3324 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3329 if (guideProcess && ekosLiveClient)
3331 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3334 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3337 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3345 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3347 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3349 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3355 connect(captureModule(), &Ekos::Capture::captureComplete,
3357 connect(captureModule(), &Ekos::Capture::captureStarting,
3359 connect(captureModule(), &Ekos::Capture::captureAborted,
3363 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3365 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3373 connect(guideModule(), &Ekos::Guide::newStatus,
3376 connect(guideModule(), &Ekos::Guide::guideStats,
3383 if (focusProcess && analyzeProcess)
3385 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3389 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3391 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3393 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3398 if (alignProcess && analyzeProcess)
3400 connect(alignModule(), &Ekos::Align::newStatus,
3406 if (mountProcess && analyzeProcess)
3412 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3417void Manager::setEkosLiveConnected(
bool enabled)
3419 ekosLiveClient.get()->setConnected(enabled);
3422void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3424 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3427void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3429 ekosLiveClient.get()->setUser(username, password);
3432bool Manager::ekosLiveStatus()
3434 return ekosLiveClient.get()->isConnected();
3440 if (!primaryDriver || !secondaryDriver)
3443 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3444 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3447void Manager::restartDriver(
const QString &deviceName)
3449 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3452 for (
auto &oneDevice : INDIListener::devices())
3454 if (oneDevice->getDeviceName() == deviceName)
3456 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3462 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3465void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3468 if (name ==
"LOGGING")
3470 Options::setDisableLogging(!enabled);
3474 else if (name ==
"FILE")
3476 Options::setLogToFile(enabled);
3480 else if (name ==
"DEFAULT")
3482 Options::setLogToDefault(enabled);
3487 else if (name ==
"VERBOSE")
3489 Options::setVerboseLogging(enabled);
3493 else if (name ==
"INDI")
3495 Options::setINDILogging(enabled);
3498 else if (name ==
"FITS")
3500 Options::setFITSLogging(enabled);
3503 else if (name ==
"CAPTURE")
3505 Options::setCaptureLogging(enabled);
3506 Options::setINDICCDLogging(enabled);
3507 Options::setINDIFilterWheelLogging(enabled);
3510 else if (name ==
"FOCUS")
3512 Options::setFocusLogging(enabled);
3513 Options::setINDIFocuserLogging(enabled);
3516 else if (name ==
"GUIDE")
3518 Options::setGuideLogging(enabled);
3519 Options::setINDICCDLogging(enabled);
3522 else if (name ==
"ALIGNMENT")
3524 Options::setAlignmentLogging(enabled);
3527 else if (name ==
"MOUNT")
3529 Options::setMountLogging(enabled);
3530 Options::setINDIMountLogging(enabled);
3533 else if (name ==
"SCHEDULER")
3535 Options::setSchedulerLogging(enabled);
3538 else if (name ==
"OBSERVATORY")
3540 Options::setObservatoryLogging(enabled);
3545void Manager::acceptPortSelection()
3548 m_PortSelector->accept();
3551void Manager::setPortSelectionComplete()
3553 if (m_CurrentProfile->portSelector)
3556 m_CurrentProfile->portSelector =
false;
3557 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3560 if (m_CurrentProfile->autoConnect)
3564void Manager::activateModule(
const QString &name,
bool popup)
3566 auto child = toolsWidget->findChild<QWidget *>(
name);
3569 toolsWidget->setCurrentWidget(child);
3581 if (device->isConnected())
3583 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3590 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3596 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3598 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3605 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3610 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3616 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3621 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3625 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3629 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3636void Manager::setDeviceReady()
3640 if (isINDIReady() ==
false)
3642 auto device =
static_cast<ISD::GenericDevice*
>(sender());
3646 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3649 if (m_CurrentProfile->portSelector)
3655 if (!m_PortSelector)
3656 m_PortSelectorTimer.start();
3660 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3665 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3668 if (m_ekosStatus != Ekos::Success)
3673 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3675 for (
auto &device : INDIListener::devices())
3676 syncGenericDevice(device);
3677 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3681void Manager::createFilterManager(ISD::FilterWheel *device)
3683 auto name = device->getDeviceName();
3684 if (m_FilterManagers.contains(name) ==
false)
3686 QSharedPointer<FilterManager> newFM(
new FilterManager(
this));
3687 newFM->setFilterWheel(device);
3688 m_FilterManagers.insert(name, std::move(newFM));
3691 m_FilterManagers[
name]->setFilterWheel(device);
3697 if (m_FilterManagers.contains(name))
3699 fm = m_FilterManagers[
name];
3707 if (m_FilterManagers.size() > 0)
3709 fm = m_FilterManagers.values()[0];
3715void Manager::createRotatorController(
ISD::Rotator *device)
3717 auto Name = device->getDeviceName();
3718 if (m_RotatorControllers.contains(Name) ==
false)
3720 QSharedPointer<RotatorSettings> newRC(
new RotatorSettings(
this));
3722 m_RotatorControllers[Name] = newRC;
3728 if (m_RotatorControllers.contains(Name))
3730 rs = m_RotatorControllers[Name];
3736bool Manager::existRotatorController()
3738 return (!m_RotatorControllers.empty());
3741void Manager::setFITSfromFile(
bool previewFromFile)
3743 if (previewFromFile && !FITSfromFile)
3746 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3747 FITSfromFile = previewFromFile;
3748 appendLogText(
i18n(
"Preview source set to external"));
3750 else if (!previewFromFile && FITSfromFile)
3753 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3754 FITSfromFile = previewFromFile;
3755 appendLogText(
i18n(
"Preview source reset to internal"));
3759void Manager::previewFile(
QString filePath)
3761 capturePreview->updateJobPreview(filePath);
3762 appendLogText(
i18n(
"Received external preview file"));
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.
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.
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.
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
void setRealTime(bool on=true)
Realtime mode will lock SimClock with system clock.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
The sky coordinates of a point in the sky.
const CachingDms & dec() const
const CachingDms & ra0() const
const CachingDms & ra() const
const CachingDms & dec0() const
An angle, stored as degrees, but expressible in many ways.
static dms fromString(const QString &s, bool deg)
Static function to create a DMS object from a QString.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
const double & Degrees() const
void setTarget(const SkyPoint &targetCoord)
Set the alignment target where the mount is expected to point at.
void setTelescopeCoordinates(const SkyPoint &position)
Set the coordinates that the mount reports as its position.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString fullName(const PartType &type)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
CaptureState
Capture states.
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
GeoCoordinates geo(const QVariant &location)
QVariant location(const QVariant &res)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString name(StandardAction id)
QString label(StandardShortcut id)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void currentTextChanged(const QString &text)
QCoreApplication * instance()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
void setFuture(const QFuture< T > &future)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
qsizetype count() const const
bool isEmpty() const const
qsizetype length() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QByteArray readAllStandardOutput()
void start(OpenMode mode)
bool waitForFinished(int msecs)
QString & append(QChar ch)
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