9 #include "ekosadaptor.h"
11 #include "kstarsdata.h"
14 #include "profileeditor.h"
15 #include "profilewizard.h"
18 #include "auxiliary/darklibrary.h"
19 #include "auxiliary/QProgressIndicator.h"
20 #include "auxiliary/ksmessagebox.h"
21 #include "capture/sequencejob.h"
22 #include "fitsviewer/fitstab.h"
23 #include "fitsviewer/fitsview.h"
24 #include "fitsviewer/fitsdata.h"
25 #include "indi/clientmanager.h"
26 #include "indi/driverinfo.h"
27 #include "indi/drivermanager.h"
28 #include "indi/guimanager.h"
29 #include "indi/indielement.h"
30 #include "indi/indilistener.h"
31 #include "indi/indiproperty.h"
32 #include "indi/indiwebmanager.h"
33 #include "indi/indigps.h"
34 #include "indi/indiguider.h"
36 #include "ekoslive/ekosliveclient.h"
37 #include "ekoslive/message.h"
38 #include "ekoslive/media.h"
40 #include <basedevice.h>
42 #include <KConfigDialog>
43 #include <KMessageBox>
44 #include <KActionCollection>
45 #include <KNotifications/KNotification>
47 #include <QFutureWatcher>
50 #include <ekos_debug.h>
52 #define MAX_REMOTE_INDI_TIMEOUT 15000
53 #define MAX_LOCAL_INDI_TIMEOUT 10000
58 Manager *Manager::_Manager =
nullptr;
60 Manager *Manager::Instance()
62 if (_Manager ==
nullptr)
63 _Manager =
new Manager(Options::independentWindowEkos() ?
nullptr :
KStars::Instance());
77 if (Options::independentWindowEkos())
86 if (Options::independentWindowEkos())
93 deviceSplitter->setSizes(
QList<int>({20000, 10000}));
95 qRegisterMetaType<Ekos::CommunicationStatus>(
"Ekos::CommunicationStatus");
96 qDBusRegisterMetaType<Ekos::CommunicationStatus>();
98 new EkosAdaptor(
this);
104 profileModel->setHorizontalHeaderLabels(
QStringList() <<
"id"
109 m_CountdownTimer.setInterval(1000);
112 toolsWidget->setIconSize(
QSize(48, 48));
116 toolsWidget->setTabEnabled(1,
false);
119 toolsWidget->setTabEnabled(2,
false);
124 processINDIB->setToolTip(
i18n(
"Start"));
131 ekosLiveClient.reset(
new EkosLive::Client(
this));
132 connect(ekosLiveClient.get(), &EkosLive::Client::connected,
this, [
this]()
134 emit ekosLiveStatusChanged(true);
136 connect(ekosLiveClient.get(), &EkosLive::Client::disconnected,
this, [
this]()
138 emit ekosLiveStatusChanged(false);
145 ekosLiveClient.get()->
show();
146 ekosLiveClient.get()->
raise();
149 connect(
this, &Manager::ekosStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setEkosStatingStatus);
150 connect(ekosLiveClient.get()->message(), &EkosLive::Message::connected,
this, [&]()
152 ekosLiveB->setIcon(QIcon(
":/icons/cloud-online.svg"));
154 connect(ekosLiveClient.get()->message(), &EkosLive::Message::disconnected,
this, [&]()
156 ekosLiveB->setIcon(QIcon::fromTheme(
"folder-cloud"));
158 connect(ekosLiveClient.get()->media(), &EkosLive::Media::newBoundingRect, ekosLiveClient.get()->message(),
159 &EkosLive::Message::setBoundingRect);
160 connect(ekosLiveClient.get()->message(), &EkosLive::Message::resetPolarView, ekosLiveClient.get()->media(),
161 &EkosLive::Media::resetPolarView);
162 connect(KSMessageBox::Instance(), &KSMessageBox::newMessage, ekosLiveClient.get()->message(),
163 &EkosLive::Message::sendDialog);
166 m_PortSelectorTimer.setInterval(500);
167 m_PortSelectorTimer.setSingleShot(
true);
170 if (m_PortSelector && currentProfile->portSelector)
172 if (m_PortSelector->shouldShow())
174 m_PortSelector->show();
175 m_PortSelector->raise();
177 ekosLiveClient.get()->message()->requestPortSelection(true);
180 else if (currentProfile->autoConnect)
181 setPortSelectionComplete();
188 m_PortSelector->show();
189 m_PortSelector->raise();
193 connect(
this, &Ekos::Manager::ekosStatusChanged,
this, [&](Ekos::CommunicationStatus status)
195 indiControlPanelB->setEnabled(status == Ekos::Success);
196 connectB->setEnabled(
false);
197 disconnectB->setEnabled(
false);
198 profileGroup->setEnabled(status == Ekos::Idle || status == Ekos::Error);
199 m_isStarted = (
status == Ekos::Success ||
status == Ekos::Pending);
200 if (status == Ekos::Success)
203 processINDIB->setToolTip(
i18n(
"Stop"));
204 setWindowTitle(
i18nc(
"@title:window",
"Ekos - %1 Profile", currentProfile->name));
206 else if (status == Ekos::Error || status == Ekos::Idle)
209 processINDIB->setToolTip(
i18n(
"Start"));
214 processINDIB->setToolTip(
i18n(
"Connection in progress. Click to abort."));
247 Options::setProfile(text);
248 if (text ==
"Simulators")
250 editProfileB->setEnabled(
false);
251 deleteProfileB->setEnabled(
false);
255 editProfileB->setEnabled(
true);
256 deleteProfileB->setEnabled(
true);
262 settleTimer.setInterval(1000);
265 if (m_settleStatus != Ekos::Success)
267 m_settleStatus = Ekos::Success;
268 emit settleStatusChanged(m_settleStatus);
291 connect(customDriversB, &
QPushButton::clicked, DriverManager::Instance(), &DriverManager::showCustomDrivers);
304 toolsWidget->tabBar()->setTabIcon(0,
QIcon(
":/icons/ekos_setup.png"));
305 toolsWidget->tabBar()->setTabToolTip(0,
i18n(
"Setup"));
308 schedulerProcess.reset(
new Scheduler());
309 int index = addModuleTab(EkosModule::Scheduler, schedulerProcess.get(),
QIcon(
":/icons/ekos_scheduler.png"));
310 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Scheduler"));
311 capturePreview->shareSchedulerProcess(schedulerProcess.get());
312 connect(schedulerProcess.get(), &Scheduler::newLog,
this, &Ekos::Manager::updateLog);
313 connect(schedulerProcess.get(), &Ekos::Scheduler::newTarget, [&](
const QString & target)
315 mountTarget->setText(target);
316 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"target", target}}));
321 index = addModuleTab(EkosModule::Analyze, analyzeProcess.get(),
QIcon(
":/icons/ekos_analyze.png"));
322 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Analyze"));
324 numPermanentTabs = index + 1;
332 m_SummaryView.reset(
new SummaryFITSView(capturePreview->previewWidget));
336 m_SummaryView->createFloatingToolBar();
337 m_SummaryView->setCursorMode(FITSView::dragCursor);
338 m_SummaryView->showProcessInfo(
false);
339 capturePreview->setSummaryFITSView(m_SummaryView.get());
351 if (Options::ekosLeftIcons())
357 for (
int i = 0; i < numPermanentTabs; ++i)
359 QIcon icon = toolsWidget->tabIcon(i);
362 toolsWidget->setTabIcon(i, icon);
370 for (
auto &button : qButtons)
371 button->setAutoDefault(
false);
374 resize(Options::ekosWindowWidth(), Options::ekosWindowHeight());
391 toolsWidget->disconnect(
this);
408 Options::setEkosWindowWidth(width());
409 Options::setEkosWindowHeight(height());
421 if (profileWizardLaunched ==
false && profiles.count() == 1)
423 profileWizardLaunched =
true;
430 focusManager->updateFocusDetailView();
431 guideManager->updateGuideDetailView();
434 void Manager::loadProfiles()
439 profileModel->clear();
441 for (
auto &pi : profiles)
447 profileModel->appendRow(info);
450 profileModel->sort(0);
451 profileCombo->blockSignals(
true);
452 profileCombo->setModel(profileModel.get());
453 profileCombo->setModelColumn(1);
454 profileCombo->blockSignals(
false);
457 int index = profileCombo->findText(Options::profile());
461 profileCombo->setCurrentIndex(index);
464 int Manager::addModuleTab(Manager::EkosModule module,
QWidget *tab,
const QIcon &icon)
469 case EkosModule::Observatory:
470 index += guideProcess ? 1 : 0;
471 case EkosModule::Guide:
472 index += alignProcess ? 1 : 0;
473 case EkosModule::Align:
474 index += mountProcess ? 1 : 0;
475 case EkosModule::Mount:
476 index += focusProcess ? 1 : 0;
477 case EkosModule::Focus:
478 index += captureProcess ? 1 : 0;
479 case EkosModule::Capture:
480 index += analyzeProcess ? 1 : 0;
481 case EkosModule::Analyze:
482 index += schedulerProcess ? 1 : 0;
483 case EkosModule::Scheduler:
485 case EkosModule::Setup:
489 index = toolsWidget->count();
493 toolsWidget->insertTab(index, tab, icon,
"");
497 void Manager::loadDrivers()
499 for (
auto &dv : DriverManager::Instance()->getDrivers())
501 if (dv->getDriverSource() != HOST_SOURCE)
502 driversList[dv->getLabel()] = dv;
506 void Manager::reset()
508 qCDebug(KSTARS_EKOS) <<
"Resetting Ekos Manager...";
511 filterManager.reset(
new Ekos::FilterManager());
517 m_GenericDevices.clear();
519 captureProcess.reset();
520 focusProcess.reset();
521 guideProcess.reset();
522 alignProcess.reset();
523 mountProcess.reset();
526 DarkLibrary::Release();
527 m_PortSelector.reset();
528 m_PortSelectorTimer.stop();
530 Ekos::CommunicationStatus previousStatus;
532 previousStatus = m_settleStatus;
533 m_settleStatus = Ekos::Idle;
534 if (previousStatus != m_settleStatus)
535 emit settleStatusChanged(m_settleStatus);
537 previousStatus = m_ekosStatus;
538 m_ekosStatus = Ekos::Idle;
539 if (previousStatus != m_ekosStatus)
540 emit ekosStatusChanged(m_ekosStatus);
542 previousStatus = m_indiStatus;
543 m_indiStatus = Ekos::Idle;
544 if (previousStatus != m_indiStatus)
545 emit indiStatusChanged(m_indiStatus);
547 connectB->setEnabled(
false);
548 disconnectB->setEnabled(
false);
550 processINDIB->setEnabled(
true);
552 mountGroup->setEnabled(
false);
553 capturePreview->setEnabled(
false);
554 capturePreview->reset();
555 mountStatus->setText(
i18n(
"Idle"));
556 mountStatus->setStyleSheet(
QString());
557 focusManager->reset();
558 guideManager->reset();
563 processINDIB->setToolTip(
i18n(
"Start"));
566 void Manager::processINDI()
568 if (m_isStarted ==
false)
577 m_PortSelector.reset();
578 m_PortSelectorTimer.stop();
579 m_CountdownTimer.stop();
580 portSelectorB->setEnabled(
false);
583 indiHubAgent->terminate();
585 profileGroup->setEnabled(
true);
587 setWindowTitle(
i18nc(
"@title:window",
"Ekos"));
590 void Manager::start()
593 if (m_ekosStatus == Ekos::Pending || m_ekosStatus == Ekos::Success)
595 qCWarning(KSTARS_EKOS) <<
"Ekos Manager start called but current Ekos Status is" << m_ekosStatus <<
"Ignoring request.";
600 qDeleteAll(managedDrivers);
601 managedDrivers.clear();
604 if (KStarsData::Instance()->clock()->isActive() ==
false)
614 currentProfile = getCurrentProfile();
615 m_LocalMode = currentProfile->isLocal();
618 updateProfileLocation(currentProfile);
620 bool haveCCD =
false, haveGuider =
false;
624 if (currentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
626 Options::setPHD2Host(currentProfile->guiderhost);
627 Options::setPHD2Port(currentProfile->guiderport);
629 else if (currentProfile->guidertype == Ekos::Guide::GUIDE_LINGUIDER)
631 Options::setLinGuiderHost(currentProfile->guiderhost);
632 Options::setLinGuiderPort(currentProfile->guiderport);
641 profileScripts = doc.
array();
646 DriverInfo * drv = driversList.value(currentProfile->mount());
649 managedDrivers.append(drv->clone());
651 drv = driversList.value(currentProfile->ccd());
654 managedDrivers.append(drv->clone());
658 Options::setGuiderType(currentProfile->guidertype);
660 drv = driversList.value(currentProfile->guider());
671 if (haveCCD && currentProfile->guider() == currentProfile->ccd())
673 if (checkUniqueBinaryDriver( driversList.value(currentProfile->ccd()), drv))
679 drv->setUniqueLabel(drv->getLabel() +
" Guide");
684 managedDrivers.append(drv->clone());
687 drv = driversList.value(currentProfile->ao());
689 managedDrivers.append(drv->clone());
691 drv = driversList.value(currentProfile->filter());
693 managedDrivers.append(drv->clone());
695 drv = driversList.value(currentProfile->focuser());
697 managedDrivers.append(drv->clone());
699 drv = driversList.value(currentProfile->dome());
701 managedDrivers.append(drv->clone());
703 drv = driversList.value(currentProfile->weather());
705 managedDrivers.append(drv->clone());
707 drv = driversList.value(currentProfile->aux1());
710 if (!checkUniqueBinaryDriver(driversList.value(currentProfile->ccd()), drv) &&
711 !checkUniqueBinaryDriver(driversList.value(currentProfile->guider()), drv))
712 managedDrivers.append(drv->clone());
714 drv = driversList.value(currentProfile->aux2());
717 if (!checkUniqueBinaryDriver(driversList.value(currentProfile->ccd()), drv) &&
718 !checkUniqueBinaryDriver(driversList.value(currentProfile->guider()), drv))
719 managedDrivers.append(drv->clone());
722 drv = driversList.value(currentProfile->aux3());
725 if (!checkUniqueBinaryDriver(driversList.value(currentProfile->ccd()), drv) &&
726 !checkUniqueBinaryDriver(driversList.value(currentProfile->guider()), drv))
727 managedDrivers.append(drv->clone());
730 drv = driversList.value(currentProfile->aux4());
733 if (!checkUniqueBinaryDriver(driversList.value(currentProfile->ccd()), drv) &&
734 !checkUniqueBinaryDriver(driversList.value(currentProfile->guider()), drv))
735 managedDrivers.append(drv->clone());
739 if (currentProfile->remotedrivers.isEmpty() ==
false && currentProfile->remotedrivers.contains(
"@"))
741 for (
auto remoteDriver : currentProfile->remotedrivers.split(
","))
753 QStringList device_location = remoteDriver.split(
'@');
756 if (device_location.
length() > 0)
757 name = device_location[0];
760 if (device_location.
length() > 1)
761 hostport = device_location[1];
777 dv->setRemoteHost(
host);
778 dv->setRemotePort(port);
784 dv->setUniqueLabel(label);
785 managedDrivers.append(dv);
790 if (haveCCD ==
false && haveGuider ==
false && currentProfile->remotedrivers.isEmpty())
792 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
793 managedDrivers.clear();
794 m_ekosStatus = Ekos::Error;
795 emit ekosStatusChanged(m_ekosStatus);
799 nDevices = managedDrivers.count();
805 remote_indi->setHostParameters(currentProfile->host, currentProfile->port);
807 remote_indi->setDriverSource(GENERATED_SOURCE);
809 managedDrivers.append(remote_indi);
811 haveCCD = currentProfile->drivers.contains(
"CCD");
812 haveGuider = currentProfile->drivers.contains(
"Guider");
814 Options::setGuiderType(currentProfile->guidertype);
816 if (haveCCD ==
false && haveGuider ==
false && currentProfile->remotedrivers.isEmpty())
818 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
819 delete (remote_indi);
821 m_ekosStatus = Ekos::Error;
822 emit ekosStatusChanged(m_ekosStatus);
826 nDevices = currentProfile->drivers.count();
832 for (
const auto &oneRule : qAsConst(profileScripts))
834 auto matchingDriver = std::find_if(managedDrivers.begin(), managedDrivers.end(), [oneRule](
const auto & oneDriver)
836 return oneDriver->getLabel() == oneRule.toObject()[
"Driver"].toString();
839 if (matchingDriver != managedDrivers.end())
841 (*matchingDriver)->setStartupRule(oneRule.toObject());
842 sortedList.
append(*matchingDriver);
850 for (
auto &oneDriver : managedDrivers)
852 if (sortedList.
contains(oneDriver) ==
false)
853 sortedList.
append(oneDriver);
856 managedDrivers = sortedList;
859 connect(DriverManager::Instance(), &DriverManager::serverStarted,
this,
861 connect(DriverManager::Instance(), &DriverManager::serverFailed,
this,
865 connect(DriverManager::Instance(), &DriverManager::clientStarted,
this,
867 connect(DriverManager::Instance(), &DriverManager::clientFailed,
this,
869 connect(DriverManager::Instance(), &DriverManager::clientTerminated,
this,
872 connect(INDIListener::Instance(), &INDIListener::newDevice,
this, &Ekos::Manager::processNewDevice);
873 connect(INDIListener::Instance(), &INDIListener::deviceRemoved,
this, &Ekos::Manager::removeDevice,
Qt::DirectConnection);
877 if (m_LocalMode || currentProfile->host ==
"localhost")
879 if (isRunning(
"PTPCamera"))
881 if (KMessageBox::Yes ==
883 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?"),
885 "ekos_shutdown_PTPCamera")))
889 p.
start(
"killall PTPCamera");
897 auto executeStartINDIServices = [
this]()
899 appendLogText(
i18n(
"Starting INDI services..."));
901 m_ekosStatus = Ekos::Pending;
902 emit ekosStatusChanged(m_ekosStatus);
904 DriverManager::Instance()->startDevices(managedDrivers);
908 if (isRunning(
"indiserver"))
913 DriverManager::Instance()->stopAllDevices();
916 const QString program =
"pkill";
918 arguments <<
"indiserver";
919 p.
start(program, arguments);
927 executeStartINDIServices();
930 KSMessageBox::Instance()->questionYesNo(
i18n(
"Ekos detected an instance of INDI server running. Do you wish to "
931 "shut down the existing instance before starting a new one?"),
932 i18n(
"INDI Server"), 5);
935 executeStartINDIServices();
940 auto runConnection = [
this]()
943 if (m_ekosStatus != Ekos::Pending)
947 i18n(
"Connecting to remote INDI server at %1 on port %2 ...", currentProfile->host, currentProfile->port));
949 DriverManager::Instance()->connectRemoteHost(managedDrivers.first());
952 auto runProfile = [
this, runConnection]()
955 if (m_ekosStatus != Ekos::Pending)
958 INDI::WebManager::syncCustomDrivers(currentProfile);
959 INDI::WebManager::checkVersion(currentProfile);
961 if (INDI::WebManager::areDriversRunning(currentProfile) ==
false)
963 INDI::WebManager::stopProfile(currentProfile);
965 if (INDI::WebManager::startProfile(currentProfile) ==
false)
967 appendLogText(
i18n(
"Failed to start profile on remote INDI Web Manager."));
971 appendLogText(
i18n(
"Starting profile on remote INDI Web Manager..."));
972 m_RemoteManagerStart =
true;
978 m_ekosStatus = Ekos::Pending;
979 emit ekosStatusChanged(m_ekosStatus);
982 if (currentProfile->INDIWebManagerPort > 0)
984 appendLogText(
i18n(
"Establishing communication with remote INDI Web Manager..."));
985 m_RemoteManagerStart =
false;
989 watcher->deleteLater();
992 if (m_ekosStatus != Ekos::Pending)
1004 appendLogText(i18n(
"Warning: INDI Web Manager is not online."));
1010 QFuture<bool> result = INDI::AsyncWebManager::isOnline(currentProfile);
1020 void Manager::setClientStarted(
const QString &
host,
int port)
1022 if (managedDrivers.size() > 0)
1026 if (currentProfile->autoConnect)
1027 appendLogText(
i18n(
"INDI services started on port %1.", port));
1030 i18n(
"INDI services started on port %1. Please connect devices.", port));
1035 i18n(
"INDI services started. Connection to remote INDI server %1:%2 is successful. Waiting for devices...",
host, port));
1042 void Manager::setClientFailed(
const QString &
host,
int port,
const QString &errorMessage)
1045 appendLogText(
i18n(
"Failed to connect to local INDI server %1:%2",
host, port));
1047 appendLogText(
i18n(
"Failed to connect to remote INDI server %1:%2",
host, port));
1052 m_ekosStatus = Ekos::Error;
1053 emit ekosStatusChanged(m_ekosStatus);
1054 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1057 void Manager::setClientTerminated(
const QString &
host,
int port,
const QString &errorMessage)
1060 appendLogText(
i18n(
"Lost connection to local INDI server %1:%2",
host, port));
1062 appendLogText(
i18n(
"Lost connection to remote INDI server %1:%2",
host, port));
1067 m_ekosStatus = Ekos::Error;
1068 emit ekosStatusChanged(m_ekosStatus);
1069 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1072 void Manager::setServerStarted(
const QString &
host,
int port)
1074 if (m_LocalMode && currentProfile->indihub != INDIHub::None)
1076 if (
QFile(Options::iNDIHubAgent()).exists())
1082 if (currentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
1083 args <<
"--phd2-server" <<
QString(
"%1:%2").
arg(currentProfile->guiderhost).
arg(currentProfile->guiderport);
1084 args <<
"--mode" << INDIHub::toString(currentProfile->indihub);
1085 indiHubAgent->start(Options::iNDIHubAgent(), args);
1087 qCDebug(KSTARS_EKOS) <<
"Started INDIHub agent.";
1097 qDeleteAll(managedDrivers);
1098 managedDrivers.clear();
1099 m_ekosStatus = Ekos::Error;
1100 emit ekosStatusChanged(m_ekosStatus);
1101 KSNotification::error(
message,
i18n(
"Error"), 15);
1122 void Manager::checkINDITimeout()
1125 if (m_ekosStatus != Ekos::Pending)
1130 m_ekosStatus = Ekos::Success;
1131 emit ekosStatusChanged(m_ekosStatus);
1138 for (
auto &drv : managedDrivers)
1140 if (drv->getDevices().
count() == 0)
1142 drv->getUniqueLabel().
isEmpty() ==
false ? drv->getUniqueLabel() : drv->getName());
1145 if (remainingDevices.
count() == 1)
1147 QString message =
i18n(
"Unable to establish:\n%1\nPlease ensure the device is connected and powered on.",
1148 remainingDevices.
at(0));
1150 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
message, KSNotification::EVENT_WARN);
1155 QString message =
i18n(
"Unable to establish the following devices:\n%1\nPlease ensure each device is connected "
1156 "and powered on.", remainingDevices.
join(
"\n"));
1158 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
message, KSNotification::EVENT_WARN);
1166 for (
auto &driver : currentProfile->drivers.values())
1168 bool driverFound =
false;
1170 for (
auto &device : m_GenericDevices)
1172 if (device->getBaseDevice()->getDriverName() == driver)
1179 if (driverFound ==
false)
1180 remainingDevices <<
QString(
"+ %1").
arg(driver);
1183 if (remainingDevices.
count() == 1)
1185 QString message =
i18n(
"Unable to remotely establish:\n%1\nPlease ensure the device is connected and powered on.",
1186 remainingDevices.
at(0));
1188 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
message, KSNotification::EVENT_WARN);
1193 QString message =
i18n(
"Unable to remotely establish the following devices:\n%1\nPlease ensure each device is connected "
1194 "and powered on.", remainingDevices.
join(
"\n"));
1196 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
message, KSNotification::EVENT_WARN);
1201 m_ekosStatus = Ekos::Error;
1204 void Manager::connectDevices()
1209 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1211 for (
auto &device : m_GenericDevices)
1213 if (device->isConnected())
1216 if (m_GenericDevices.count() == nConnected)
1218 m_indiStatus = Ekos::Success;
1219 emit indiStatusChanged(m_indiStatus);
1223 m_indiStatus = Ekos::Pending;
1224 if (previousStatus != m_indiStatus)
1225 emit indiStatusChanged(m_indiStatus);
1227 for (
auto &device : m_GenericDevices)
1229 qCDebug(KSTARS_EKOS) <<
"Connecting " << device->getDeviceName();
1233 connectB->setEnabled(
false);
1234 disconnectB->setEnabled(
true);
1236 appendLogText(
i18n(
"Connecting INDI devices..."));
1239 void Manager::disconnectDevices()
1241 for (
auto &device : m_GenericDevices)
1243 qCDebug(KSTARS_EKOS) <<
"Disconnecting " << device->getDeviceName();
1244 device->Disconnect();
1247 appendLogText(
i18n(
"Disconnecting INDI devices..."));
1250 void Manager::cleanDevices(
bool stopDrivers)
1252 if (m_ekosStatus == Ekos::Idle)
1255 if (mountProcess.get())
1256 mountProcess->stopTimers();
1259 DriverManager::Instance()->disconnect(
this);
1261 if (managedDrivers.isEmpty() ==
false)
1266 DriverManager::Instance()->stopDevices(managedDrivers);
1272 DriverManager::Instance()->disconnectRemoteHost(managedDrivers.first());
1274 if (m_RemoteManagerStart && currentProfile->INDIWebManagerPort != -1)
1275 INDI::WebManager::stopProfile(currentProfile);
1277 m_RemoteManagerStart =
false;
1283 profileGroup->setEnabled(
true);
1285 appendLogText(
i18n(
"INDI services stopped."));
1290 qCInfo(KSTARS_EKOS) <<
"Ekos received a new device: " << device->getDeviceName();
1292 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1294 for(
auto &oneDevice : m_GenericDevices)
1296 if (oneDevice->getDeviceName() == device->getDeviceName())
1298 qCWarning(KSTARS_EKOS) <<
"Found duplicate device, ignoring...";
1304 m_indiStatus = Ekos::Idle;
1305 if (previousStatus != m_indiStatus)
1306 emit indiStatusChanged(m_indiStatus);
1308 m_GenericDevices.append(device);
1312 connect(device, &ISD::GenericDevice::ready,
this, &Ekos::Manager::setDeviceReady,
Qt::UniqueConnection);
1313 connect(device, &ISD::GenericDevice::newMount,
this, &Ekos::Manager::addMount,
Qt::UniqueConnection);
1314 connect(device, &ISD::GenericDevice::newCamera,
this, &Ekos::Manager::addCamera,
Qt::UniqueConnection);
1315 connect(device, &ISD::GenericDevice::newGuider,
this, &Ekos::Manager::addGuider,
Qt::UniqueConnection);
1316 connect(device, &ISD::GenericDevice::newFilterWheel,
this, &Ekos::Manager::addFilterWheel,
Qt::UniqueConnection);
1317 connect(device, &ISD::GenericDevice::newFocuser,
this, &Ekos::Manager::addFocuser,
Qt::UniqueConnection);
1318 connect(device, &ISD::GenericDevice::newDome,
this, &Ekos::Manager::addDome,
Qt::UniqueConnection);
1319 connect(device, &ISD::GenericDevice::newRotator,
this, &Ekos::Manager::addRotator,
Qt::UniqueConnection);
1320 connect(device, &ISD::GenericDevice::newWeather,
this, &Ekos::Manager::addWeather,
Qt::UniqueConnection);
1321 connect(device, &ISD::GenericDevice::newDustCap,
this, &Ekos::Manager::addDustCap,
Qt::UniqueConnection);
1322 connect(device, &ISD::GenericDevice::newLightBox,
this, &Ekos::Manager::addLightBox,
Qt::UniqueConnection);
1323 connect(device, &ISD::GenericDevice::newGPS,
this, &Ekos::Manager::addGPS,
Qt::UniqueConnection);
1325 connect(device, &ISD::GenericDevice::Connected,
this, &Ekos::Manager::deviceConnected,
Qt::UniqueConnection);
1326 connect(device, &ISD::GenericDevice::Disconnected,
this, &Ekos::Manager::deviceDisconnected,
Qt::UniqueConnection);
1327 connect(device, &ISD::GenericDevice::propertyDefined,
this, &Ekos::Manager::processNewProperty,
Qt::UniqueConnection);
1328 connect(device, &ISD::GenericDevice::propertyDeleted,
this, &Ekos::Manager::processDeleteProperty,
Qt::UniqueConnection);
1329 connect(device, &ISD::GenericDevice::interfaceDefined,
this, &Ekos::Manager::syncActiveDevices,
Qt::UniqueConnection);
1331 connect(device, &ISD::GenericDevice::numberUpdated,
this, &Ekos::Manager::processNewNumber,
Qt::UniqueConnection);
1332 connect(device, &ISD::GenericDevice::switchUpdated,
this, &Ekos::Manager::processNewSwitch,
Qt::UniqueConnection);
1333 connect(device, &ISD::GenericDevice::textUpdated,
this, &Ekos::Manager::processNewText,
Qt::UniqueConnection);
1334 connect(device, &ISD::GenericDevice::lightUpdated,
this, &Ekos::Manager::processNewLight,
Qt::UniqueConnection);
1335 connect(device, &ISD::GenericDevice::BLOBUpdated,
this, &Ekos::Manager::processNewBLOB,
Qt::UniqueConnection);
1339 if (currentProfile->ccd() != currentProfile->guider())
1341 for (
auto &oneCamera : m_GenericDevices)
1344 m_PrimaryCamera =
QString(oneCamera->getDeviceName());
1345 else if (oneCamera->getDeviceName().startsWith(currentProfile->guider(),
Qt::CaseInsensitive))
1346 m_GuideCamera =
QString(oneCamera->getDeviceName());
1352 m_ekosStatus = Ekos::Success;
1353 emit ekosStatusChanged(m_ekosStatus);
1355 connectB->setEnabled(
true);
1356 disconnectB->setEnabled(
false);
1358 if (m_LocalMode ==
false && nDevices == 0)
1360 if (currentProfile->autoConnect)
1361 appendLogText(
i18n(
"Remote devices established."));
1363 appendLogText(
i18n(
"Remote devices established. Please connect devices."));
1366 if (!m_PortSelector)
1368 portSelectorB->setEnabled(
false);
1370 connect(m_PortSelector.get(), &Selector::Dialog::accepted,
this, &Manager::setPortSelectionComplete);
1375 void Manager::deviceConnected()
1377 connectB->setEnabled(
false);
1378 disconnectB->setEnabled(
true);
1379 processINDIB->setEnabled(
false);
1381 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1383 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1385 if (Options::verboseLogging())
1387 qCInfo(KSTARS_EKOS) << device->getDeviceName()
1388 <<
"Version:" << device->getDriverVersion()
1389 <<
"Interface:" << device->getDriverInterface()
1393 int nConnectedDevices = 0;
1395 for (
auto &device : m_GenericDevices)
1397 if (device->isConnected())
1398 nConnectedDevices++;
1401 qCDebug(KSTARS_EKOS) << nConnectedDevices <<
" devices connected out of " << m_GenericDevices.count();
1403 if (nConnectedDevices >= currentProfile->drivers.count())
1406 m_indiStatus = Ekos::Success;
1407 qCInfo(KSTARS_EKOS) <<
"All INDI devices are now connected.";
1410 m_indiStatus = Ekos::Pending;
1412 if (previousStatus != m_indiStatus)
1413 emit indiStatusChanged(m_indiStatus);
1415 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
1417 if (mountProcess.get() !=
nullptr)
1419 mountProcess->setEnabled(
true);
1420 if (alignProcess.get() !=
nullptr)
1421 alignProcess->setEnabled(
true);
1424 else if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
1426 if (captureProcess.get() !=
nullptr)
1428 captureProcess->setEnabled(
true);
1429 capturePreview->setEnabled(
true);
1431 if (focusProcess.get() !=
nullptr)
1432 focusProcess->setEnabled(
true);
1433 if (alignProcess.get() !=
nullptr)
1435 if (mountProcess.get() && mountProcess->isEnabled())
1436 alignProcess->setEnabled(
true);
1438 alignProcess->setEnabled(
false);
1440 if (guideProcess.get() !=
nullptr)
1441 guideProcess->setEnabled(
true);
1443 else if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
1445 if (focusProcess.get() !=
nullptr)
1446 focusProcess->setEnabled(
true);
1449 if (Options::neverLoadConfig())
1452 INDIConfig tConfig = Options::loadConfigOnConnection() ? LOAD_LAST_CONFIG : LOAD_DEFAULT_CONFIG;
1454 for (
auto &oneDevice : m_GenericDevices)
1456 if (oneDevice == device)
1458 connect(device, &ISD::GenericDevice::switchUpdated,
this, &Ekos::Manager::watchDebugProperty,
Qt::UniqueConnection);
1460 auto configProp = device->getBaseDevice()->getSwitch(
"CONFIG_PROCESS");
1461 if (configProp && configProp->getState() == IPS_IDLE)
1462 device->setConfig(tConfig);
1468 void Manager::deviceDisconnected()
1472 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1476 if (dev->getState(
"CONNECTION") == IPS_ALERT)
1477 m_indiStatus = Ekos::Error;
1478 else if (dev->getState(
"CONNECTION") == IPS_BUSY)
1479 m_indiStatus = Ekos::Pending;
1481 m_indiStatus = Ekos::Idle;
1483 if (Options::verboseLogging())
1484 qCDebug(KSTARS_EKOS) << dev->getDeviceName() <<
" is disconnected.";
1487 if (m_indiStatus == Ekos::Error)
1489 QString message =
i18n(
"%1 failed to connect.\nPlease ensure the device is connected and powered on.",
1490 dev->getDeviceName());
1492 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
message, KSNotification::EVENT_WARN);
1494 else if (m_indiStatus == Ekos::Idle)
1501 m_indiStatus = Ekos::Idle;
1503 if (previousStatus != m_indiStatus)
1504 emit indiStatusChanged(m_indiStatus);
1506 connectB->setEnabled(
true);
1507 disconnectB->setEnabled(
false);
1508 processINDIB->setEnabled(
true);
1510 if (dev !=
nullptr && dev->getBaseDevice() &&
1511 (dev->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE))
1513 if (mountProcess.get() !=
nullptr)
1514 mountProcess->setEnabled(
false);
1520 syncGenericDevice(device->genericDevice());
1522 ekosLiveClient->message()->sendMounts();
1523 ekosLiveClient->message()->sendScopes();
1525 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1530 syncGenericDevice(device->genericDevice());
1532 captureProcess->setEnabled(
true);
1533 capturePreview->setEnabled(
true);
1535 ekosLiveClient.get()->message()->sendCameras();
1536 ekosLiveClient.get()->media()->registerCameras();
1538 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1541 void Manager::addFilterWheel(ISD::FilterWheel * device)
1543 syncGenericDevice(device->genericDevice());
1545 ekosLiveClient.get()->message()->sendFilterWheels();
1547 appendLogText(
i18n(
"%1 filter is online.", device->getDeviceName()));
1552 syncGenericDevice(device->genericDevice());
1554 appendLogText(
i18n(
"%1 focuser is online.", device->getDeviceName()));
1559 syncGenericDevice(device->genericDevice());
1561 appendLogText(
i18n(
"Rotator %1 is online.", device->getDeviceName()));
1564 void Manager::addDome(
ISD::Dome * device)
1566 syncGenericDevice(device->genericDevice());
1568 ekosLiveClient.get()->message()->sendDomes();
1570 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1575 syncGenericDevice(device->genericDevice());
1577 appendLogText(
i18n(
"%1 Weather is online.", device->getDeviceName()));
1580 void Manager::addGPS(ISD::GPS * device)
1582 syncGenericDevice(device->genericDevice());
1584 appendLogText(
i18n(
"%1 GPS is online.", device->getDeviceName()));
1589 syncGenericDevice(device->genericDevice());
1591 ekosLiveClient.get()->message()->sendCaps();
1593 appendLogText(
i18n(
"%1 Dust cap is online.", device->getDeviceName()));
1598 syncGenericDevice(device->genericDevice());
1600 appendLogText(
i18n(
"%1 Light box is online.", device->getDeviceName()));
1605 createModules(device);
1610 auto camera =
dynamic_cast<ISD::Camera*
>(device->getConcreteDevice(INDI::BaseDevice::CCD_INTERFACE));
1614 if (captureProcess && captureProcess->addCamera(camera))
1617 if (Options::defaultCaptureCCD().isEmpty() ==
false)
1618 rc = captureProcess->setCamera(Options::defaultCaptureCCD());
1619 if (rc ==
false && m_PrimaryCamera.isEmpty() ==
false)
1620 captureProcess->setCamera(m_PrimaryCamera);
1624 if (focusProcess && focusProcess->addCamera(camera))
1626 if (camera->hasCooler())
1627 focusProcess->addTemperatureSource(camera->genericDevice());
1630 if (Options::defaultFocusCCD().isEmpty() ==
false)
1631 rc = focusProcess->setCamera(Options::defaultFocusCCD());
1632 if (rc ==
false && m_PrimaryCamera.isEmpty() ==
false)
1633 focusProcess->setCamera(m_PrimaryCamera);
1637 if (alignProcess && alignProcess->addCamera(camera))
1640 if (Options::defaultAlignCCD().isEmpty() ==
false)
1641 rc = alignProcess->setCamera(Options::defaultAlignCCD());
1642 if (rc ==
false && m_PrimaryCamera.isEmpty() ==
false)
1643 alignProcess->setCamera(m_PrimaryCamera);
1648 if (guideProcess && guideProcess->addCamera(camera))
1651 if (Options::defaultGuideCCD().isEmpty() ==
false)
1652 rc = guideProcess->setCamera(Options::defaultGuideCCD());
1653 if (rc ==
false && m_GuideCamera.isEmpty() ==
false)
1654 guideProcess->setCamera(m_GuideCamera);
1661 auto mount =
dynamic_cast<ISD::Mount*
>(device->getConcreteDevice(INDI::BaseDevice::TELESCOPE_INTERFACE));
1664 double primaryScopeFL = 0, primaryScopeAperture = 0, guideScopeFL = 0, guideScopeAperture = 0;
1665 getCurrentProfileTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
1666 if (mountProcess && mountProcess->addMount(mount))
1669 mountProcess->setTelescopeInfo(
QList<double>() << primaryScopeFL << primaryScopeAperture << guideScopeFL <<
1670 guideScopeAperture);
1674 captureProcess->addMount(mount);
1676 if (guideProcess && guideProcess->addMount(mount))
1677 guideProcess->setTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
1679 if (alignProcess && alignProcess->addMount(mount))
1680 alignProcess->setTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
1686 auto focuser =
dynamic_cast<ISD::Focuser*
>(device->getConcreteDevice(INDI::BaseDevice::FOCUSER_INTERFACE));
1689 if (focusProcess && focusProcess->addFocuser(focuser))
1691 if (Options::defaultFocusFocuser().isEmpty() ==
false)
1692 focusProcess->setFocuser(Options::defaultFocusFocuser());
1695 focusProcess->addTemperatureSource(focuser->genericDevice());
1702 auto filterWheel =
dynamic_cast<ISD::FilterWheel*
>(device->getConcreteDevice(INDI::BaseDevice::FILTER_INTERFACE));
1706 captureProcess->addFilterWheel(filterWheel);
1709 focusProcess->addFilterWheel(filterWheel);
1712 alignProcess->addFilterWheel(filterWheel);
1718 auto rotator =
dynamic_cast<ISD::Rotator*
>(device->getConcreteDevice(INDI::BaseDevice::ROTATOR_INTERFACE));
1722 captureProcess->addRotator(rotator);
1725 alignProcess->addRotator(rotator);
1731 auto dome =
dynamic_cast<ISD::Dome*
>(device->getConcreteDevice(INDI::BaseDevice::DOME_INTERFACE));
1742 captureProcess->addDome(dome);
1745 alignProcess->addDome(dome);
1751 auto weather =
dynamic_cast<ISD::Weather*
>(device->getConcreteDevice(INDI::BaseDevice::WEATHER_INTERFACE));
1762 focusProcess->addTemperatureSource(weather->genericDevice());
1768 auto gps =
dynamic_cast<ISD::GPS*
>(device->getConcreteDevice(INDI::BaseDevice::GPS_INTERFACE));
1772 mountProcess->addGPS(gps);
1778 auto dustCap =
dynamic_cast<ISD::DustCap*
>(device->getConcreteDevice(INDI::BaseDevice::DUSTCAP_INTERFACE));
1782 captureProcess->addDustCap(dustCap);
1788 auto lightBox =
dynamic_cast<ISD::LightBox*
>(device->getConcreteDevice(INDI::BaseDevice::LIGHTBOX_INTERFACE));
1792 captureProcess->addLightBox(lightBox);
1799 alignProcess->removeDevice(device);
1801 captureProcess->removeDevice(device);
1803 focusProcess->removeDevice(device);
1805 mountProcess->removeDevice(device);
1807 guideProcess->removeDevice(device);
1810 m_PortSelector->removeDevice(device->getDeviceName());
1812 DarkLibrary::Instance()->removeDevice(device);
1814 appendLogText(
i18n(
"%1 is offline.", device->getDeviceName()));
1820 for (
auto &oneDevice : m_GenericDevices)
1822 if (oneDevice->getDeviceName() == device->getDeviceName())
1824 m_GenericDevices.removeOne(device);
1828 if (m_GenericDevices.isEmpty())
1835 void Manager::processNewText(ITextVectorProperty * tvp)
1837 ekosLiveClient.get()->message()->processNewText(tvp);
1839 if (!strcmp(tvp->name,
"FILTER_NAME"))
1841 ekosLiveClient.get()->message()->sendFilterWheels();
1844 if (!strcmp(tvp->name,
"ACTIVE_DEVICES"))
1846 syncActiveDevices();
1850 void Manager::processNewSwitch(ISwitchVectorProperty * svp)
1852 ekosLiveClient.get()->message()->processNewSwitch(svp);
1855 void Manager::processNewLight(ILightVectorProperty * lvp)
1857 ekosLiveClient.get()->message()->processNewLight(lvp);
1860 void Manager::processNewBLOB(IBLOB * bp)
1862 ekosLiveClient.get()->media()->processNewBLOB(bp);
1865 void Manager::processNewNumber(INumberVectorProperty * nvp)
1867 ekosLiveClient.get()->message()->processNewNumber(nvp);
1869 if (!strcmp(nvp->name,
"CCD_INFO") || !strcmp(nvp->name,
"GUIDER_INFO") || !strcmp(nvp->name,
"CCD_FRAME") ||
1870 !strcmp(nvp->name,
"GUIDER_FRAME"))
1872 if (focusProcess.get() !=
nullptr)
1873 focusProcess->syncCameraInfo();
1875 if (guideProcess.get() !=
nullptr)
1876 guideProcess->syncCameraInfo();
1878 if (alignProcess.get() !=
nullptr)
1879 alignProcess->syncCameraInfo();
1885 void Manager::processDeleteProperty(
const QString &name)
1888 ekosLiveClient.get()->message()->processDeleteProperty(deviceInterface->getDeviceName(), name);
1891 void Manager::processNewProperty(INDI::Property prop)
1893 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1895 settleTimer.start();
1897 ekosLiveClient.get()->message()->processNewProperty(prop);
1899 if (prop->isNameMatch(
"DEVICE_PORT_SCAN") || prop->isNameMatch(
"CONNECTION_TYPE"))
1901 if (!m_PortSelector)
1904 connect(m_PortSelector.get(), &Selector::Dialog::accepted,
this, &Manager::setPortSelectionComplete);
1906 m_PortSelectorTimer.start();
1907 portSelectorB->setEnabled(
true);
1908 m_PortSelector->addDevice(device);
1913 if (prop->isNameMatch(
"DEBUG"))
1915 uint16_t
interface = device->getDriverInterface();
1916 if ( opsLogs->getINDIDebugInterface() & interface )
1919 auto debugSP = prop->getSwitch();
1920 debugSP->at(0)->setState(ISS_ON);
1921 debugSP->at(1)->setState(ISS_OFF);
1922 device->getDriverInfo()->getClientManager()->sendNewSwitch(debugSP);
1928 if (prop->isNameMatch(
"DEBUG_LEVEL"))
1930 uint16_t
interface = device->getDriverInterface();
1932 if ( opsLogs->getINDIDebugInterface() & interface )
1935 auto debugLevel = prop->getSwitch();
1936 for (
auto &it : *debugLevel)
1937 it.setState(ISS_ON);
1939 device->getDriverInfo()->getClientManager()->sendNewSwitch(debugLevel);
1944 if (prop->isNameMatch(
"ACTIVE_DEVICES"))
1946 if (device->getDriverInterface() > 0)
1947 syncActiveDevices();
1952 if (prop->isNameMatch(
"ASTROMETRY_SOLVER"))
1954 for (
auto &oneDevice : m_GenericDevices)
1956 if (oneDevice->getDeviceName() == prop->getDeviceName())
1959 alignProcess->setAstrometryDevice(oneDevice);
1967 if (focusProcess.get() !=
nullptr && strstr(prop->getName(),
"FOCUS_"))
1969 focusProcess->checkFocuser();
1974 void Manager::processTabChange()
1976 auto currentWidget = toolsWidget->currentWidget();
1978 if (alignProcess && alignProcess.get() == currentWidget)
1980 auto alignReady = alignProcess->isEnabled() ==
false && alignProcess->isParserOK();
1981 auto captureReady = captureProcess && captureProcess->isEnabled();
1982 auto mountReady = mountProcess && mountProcess->isEnabled();
1983 if (alignReady && captureReady && mountReady)
1984 alignProcess->setEnabled(
true);
1986 alignProcess->checkCamera();
1988 else if (captureProcess && currentWidget == captureProcess.get())
1990 captureProcess->checkCamera();
1992 else if (focusProcess && currentWidget == focusProcess.get())
1994 focusProcess->checkCamera();
1996 else if (guideProcess && currentWidget == guideProcess.get())
1998 guideProcess->checkCamera();
2004 void Manager::updateLog()
2006 QWidget * currentWidget = toolsWidget->currentWidget();
2008 if (currentWidget == setupTab)
2009 ekosLogOut->setPlainText(m_LogText.join(
"\n"));
2010 else if (currentWidget == alignProcess.get())
2011 ekosLogOut->setPlainText(alignProcess->getLogText());
2012 else if (currentWidget == captureProcess.get())
2013 ekosLogOut->setPlainText(captureProcess->getLogText());
2014 else if (currentWidget == focusProcess.get())
2015 ekosLogOut->setPlainText(focusProcess->getLogText());
2016 else if (currentWidget == guideProcess.get())
2017 ekosLogOut->setPlainText(guideProcess->getLogText());
2018 else if (currentWidget == mountProcess.get())
2019 ekosLogOut->setPlainText(mountProcess->getLogText());
2020 else if (currentWidget == schedulerProcess.get())
2021 ekosLogOut->setPlainText(schedulerProcess->getLogText());
2030 void Manager::appendLogText(
const QString &text)
2032 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
2033 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
2035 qCInfo(KSTARS_EKOS) << text;
2042 void Manager::clearLog()
2044 QWidget * currentWidget = toolsWidget->currentWidget();
2046 if (currentWidget == setupTab)
2051 else if (currentWidget == alignProcess.get())
2052 alignProcess->clearLog();
2053 else if (currentWidget == captureProcess.get())
2054 captureProcess->clearLog();
2055 else if (currentWidget == focusProcess.get())
2056 focusProcess->clearLog();
2057 else if (currentWidget == guideProcess.get())
2058 guideProcess->clearLog();
2059 else if (currentWidget == mountProcess.get())
2060 mountProcess->clearLog();
2061 else if (currentWidget == schedulerProcess.get())
2062 schedulerProcess->clearLog();
2067 void Manager::initCapture()
2069 if (captureProcess.get() !=
nullptr)
2072 captureProcess.reset(
new Capture());
2073 emit newModule(
"Capture");
2075 captureProcess->setEnabled(
false);
2076 capturePreview->shareCaptureProcess(captureProcess.get());
2077 int index = addModuleTab(EkosModule::Capture, captureProcess.get(),
QIcon(
":/icons/ekos_ccd.png"));
2078 toolsWidget->tabBar()->setTabToolTip(index,
i18nc(
"Charge-Coupled Device",
"CCD"));
2079 if (Options::ekosLeftIcons())
2083 QIcon icon = toolsWidget->tabIcon(index);
2086 toolsWidget->setTabIcon(index, icon);
2088 connect(captureProcess.get(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2089 connect(captureProcess.get(), &Ekos::Capture::newStatus,
this, &Ekos::Manager::updateCaptureStatus);
2090 connect(captureProcess.get(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
2091 connect(captureProcess.get(), &Ekos::Capture::driverTimedout,
this, &Ekos::Manager::restartDriver);
2092 connect(captureProcess.get(), &Ekos::Capture::newExposureProgress,
this, &Ekos::Manager::updateExposureProgress);
2093 capturePreview->setEnabled(
true);
2095 captureProcess->setFilterManager(filterManager);
2097 connect(filterManager.data(), &FilterManager::newStatus, capturePreview->captureStatusWidget,
2098 &CaptureStatusWidget::setFilterState);
2100 connect(schedulerProcess.get(), &Ekos::Scheduler::targetDistance,
2102 connect(schedulerProcess.get(), &Ekos::Scheduler::targetDistance,
this, [
this](
double distance)
2104 capturePreview->updateTargetDistance(distance);
2111 void Manager::initAlign()
2113 if (alignProcess.get() !=
nullptr)
2116 alignProcess.reset(
new Ekos::Align(currentProfile));
2118 emit newModule(
"Align");
2120 double primaryScopeFL = 0, primaryScopeAperture = 0, guideScopeFL = 0, guideScopeAperture = 0;
2121 getCurrentProfileTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
2122 alignProcess->setTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
2124 alignProcess->setEnabled(
false);
2125 int index = addModuleTab(EkosModule::Align, alignProcess.get(),
QIcon(
":/icons/ekos_align.png"));
2126 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Align"));
2127 connect(alignProcess.get(), &Ekos::Align::newLog,
this, &Ekos::Manager::updateLog);
2128 if (Options::ekosLeftIcons())
2132 QIcon icon = toolsWidget->tabIcon(index);
2135 toolsWidget->setTabIcon(index, icon);
2138 alignProcess->setFilterManager(filterManager);
2143 void Manager::initFocus()
2145 if (focusProcess.get() !=
nullptr)
2150 emit newModule(
"Focus");
2152 int index = addModuleTab(EkosModule::Focus, focusProcess.get(),
QIcon(
":/icons/ekos_focus.png"));
2154 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2157 connect(focusProcess.get(), &Ekos::Focus::newLog,
this, &Ekos::Manager::updateLog);
2158 connect(focusProcess.get(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2159 connect(focusProcess.get(), &Ekos::Focus::newStarPixmap, focusManager, &Ekos::FocusManager::updateFocusStarPixmap);
2160 connect(focusProcess.get(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2168 &FocusHFRVPlot::addPositionWithSigma);
2170 connect(focusProcess.get(), &
Ekos::Focus::setTitle, focusManager->hfrVPlot, &FocusHFRVPlot::setTitle);
2177 focusProcess->setFilterManager(filterManager);
2180 connect(focusProcess.get(), &Ekos::Focus::newStatus, filterManager.data(), &Ekos::FilterManager::setFocusStatus,
2182 connect(filterManager.data(), &Ekos::FilterManager::newFocusOffset, focusProcess.get(), &Ekos::Focus::adjustFocusOffset,
2184 connect(focusProcess.get(), &Ekos::Focus::focusPositionAdjusted, filterManager.data(),
2186 connect(focusProcess.get(), &Ekos::Focus::absolutePositionChanged, filterManager.data(),
2189 if (Options::ekosLeftIcons())
2193 QIcon icon = toolsWidget->tabIcon(index);
2196 toolsWidget->setTabIcon(index, icon);
2199 focusManager->init(focusProcess.get());
2200 focusManager->setEnabled(
true);
2202 for (
auto &oneDevice : m_GenericDevices)
2204 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2205 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2206 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2207 if (prop1 || prop2 || prop3)
2208 focusProcess->addTemperatureSource(oneDevice);
2214 void Manager::updateCurrentHFR(
double newHFR,
int position)
2216 focusManager->updateCurrentHFR(newHFR);
2224 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2227 void Manager::updateSigmas(
double ra,
double de)
2229 guideManager->updateSigmas(ra, de);
2231 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2233 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2236 void Manager::initMount()
2238 if (mountProcess.get() !=
nullptr)
2243 emit newModule(
"Mount");
2245 int index = addModuleTab(EkosModule::Mount, mountProcess.get(),
QIcon(
":/icons/ekos_mount.png"));
2247 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2248 connect(mountProcess.get(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2253 mountTarget->setText(name);
2254 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"target", name}}));
2256 connect(mountProcess.get(), &Ekos::Mount::pierSideChanged, [&](ISD::Mount::PierSide side)
2258 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"pierSide", side}}));
2260 connect(mountProcess.get(), &Ekos::Mount::newMeridianFlipStatus, [&](Mount::MeridianFlipStatus status)
2262 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2264 {
"meridianFlipStatus", status},
2267 connect(mountProcess.get(), &Ekos::Mount::newMeridianFlipText, [&](
const QString & text)
2270 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2272 {
"meridianFlipText", text},
2273 }), mountProcess->meridianFlipStatus() == Mount::FLIP_NONE);
2277 connect(mountProcess.get(), &Ekos::Mount::slewRateChanged, [&](
int slewRate)
2279 QJsonObject status = { {
"slewRate", slewRate} };
2280 ekosLiveClient.get()->message()->updateMountStatus(status);
2283 if (Options::ekosLeftIcons())
2287 QIcon icon = toolsWidget->tabIcon(index);
2290 toolsWidget->setTabIcon(index, icon);
2293 mountGroup->setEnabled(
true);
2294 capturePreview->shareMountProcess(mountProcess.get());
2299 void Manager::initGuide()
2301 if (guideProcess.get() ==
nullptr)
2305 emit newModule(
"Guide");
2307 double primaryScopeFL = 0, primaryScopeAperture = 0, guideScopeFL = 0, guideScopeAperture = 0;
2308 getCurrentProfileTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
2310 guideProcess->setTelescopeInfo(primaryScopeFL, primaryScopeAperture, guideScopeFL, guideScopeAperture);
2313 if (toolsWidget->indexOf(guideProcess.get()) == -1)
2318 int index = addModuleTab(EkosModule::Guide, guideProcess.get(),
QIcon(
":/icons/ekos_guide.png"));
2319 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2320 connect(guideProcess.get(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2321 connect(guideProcess.get(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2323 guideManager->setEnabled(
true);
2325 connect(guideProcess.get(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2326 connect(guideProcess.get(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2327 connect(guideProcess.get(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2328 connect(guideProcess.get(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2330 QJsonObject status = { {
"drift_ra", ra}, {
"drift_de", de} };
2331 ekosLiveClient.get()->message()->updateGuideStatus(status);
2334 if (Options::ekosLeftIcons())
2338 QIcon icon = toolsWidget->tabIcon(index);
2341 toolsWidget->setTabIcon(index, icon);
2343 guideManager->init(guideProcess.get());
2364 void Manager::addGuider(ISD::Guider * device)
2366 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2370 guideProcess->addGuider(device);
2372 if (Options::defaultGuideGuider().isEmpty() ==
false)
2373 guideProcess->setGuider(Options::defaultGuideGuider());
2376 void Manager::removeTabs()
2380 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2381 toolsWidget->removeTab(i);
2383 alignProcess.reset();
2384 captureProcess.reset();
2385 focusProcess.reset();
2386 guideProcess.reset();
2387 mountProcess.reset();
2393 bool Manager::isRunning(
const QString &process)
2400 return output.
length() > 0;
2405 <<
"-C" << process);
2412 void Manager::addObjectToScheduler(
SkyObject *
object)
2414 if (schedulerProcess.get() !=
nullptr)
2415 schedulerProcess->addObject(
object);
2418 QString Manager::getCurrentJobName()
2420 return schedulerProcess->getCurrentJobName();
2423 bool Manager::setProfile(
const QString &profileName)
2425 int index = profileCombo->findText(profileName);
2430 profileCombo->setCurrentIndex(index);
2435 void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2437 ProfileEditor editor(
this);
2438 setProfile(profileInfo[
"name"].
toString());
2439 currentProfile = getCurrentProfile();
2440 editor.setPi(currentProfile);
2441 editor.setSettings(profileInfo);
2442 editor.saveProfile();
2445 void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2447 ProfileEditor editor(
this);
2449 editor.setSettings(profileInfo);
2450 editor.saveProfile();
2453 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2454 currentProfile = getCurrentProfile();
2457 void Manager::deleteNamedProfile(
const QString &name)
2459 currentProfile = getCurrentProfile();
2461 for (
auto &pi : profiles)
2465 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == currentProfile && ekosStatus() != Idle))
2468 KStarsData::Instance()->
userdb()->DeleteProfile(pi.get());
2472 currentProfile = getCurrentProfile();
2482 for (
auto &pi : profiles)
2484 if (name == pi->name)
2485 return pi->toJson();
2495 for (
int i = 0; i < profileCombo->count(); i++)
2496 profiles << profileCombo->itemText(i);
2501 void Manager::addProfile()
2503 ProfileEditor editor(
this);
2509 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2512 currentProfile = getCurrentProfile();
2515 void Manager::editProfile()
2517 ProfileEditor editor(
this);
2519 currentProfile = getCurrentProfile();
2521 editor.setPi(currentProfile);
2525 int currentIndex = profileCombo->currentIndex();
2529 profileCombo->setCurrentIndex(currentIndex);
2532 currentProfile = getCurrentProfile();
2535 void Manager::deleteProfile()
2537 currentProfile = getCurrentProfile();
2539 if (currentProfile->name ==
"Simulators")
2542 auto executeDeleteProfile = [&]()
2544 KStarsData::Instance()->
userdb()->DeleteProfile(currentProfile);
2547 currentProfile = getCurrentProfile();
2554 executeDeleteProfile();
2557 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2558 i18n(
"Confirm Delete"));
2562 void Manager::wizardProfile()
2568 ProfileEditor editor(
this);
2570 editor.setProfileName(wz.profileName);
2571 editor.setAuxDrivers(wz.selectedAuxDrivers());
2572 if (wz.useInternalServer ==
false)
2573 editor.setHostPort(wz.host, wz.port);
2574 editor.setWebManager(wz.useWebManager);
2575 editor.setGuiderType(wz.selectedExternalGuider());
2577 editor.setConnectionOptionsEnabled(
false);
2583 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2586 currentProfile = getCurrentProfile();
2589 ProfileInfo * Manager::getCurrentProfile()
2591 ProfileInfo * currProfile =
nullptr;
2594 for (
auto &pi : profiles)
2596 if (profileCombo->currentText() == pi->name)
2598 currProfile = pi.get();
2606 void Manager::updateProfileLocation(ProfileInfo * pi)
2608 if (pi->city.isEmpty() ==
false)
2612 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2614 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2619 void Manager::updateMountStatus(ISD::Mount::Status status)
2621 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2623 if (status == lastStatus)
2628 mountStatus->setText(mountProcess.get()->statusString());
2629 mountStatus->setStyleSheet(
QString());
2633 case ISD::Mount::MOUNT_PARKING:
2634 case ISD::Mount::MOUNT_SLEWING:
2635 case ISD::Mount::MOUNT_MOVING:
2636 mountPI->setColor(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")));
2637 if (mountPI->isAnimated() ==
false)
2638 mountPI->startAnimation();
2641 case ISD::Mount::MOUNT_TRACKING:
2643 if (mountPI->isAnimated() ==
false)
2644 mountPI->startAnimation();
2648 case ISD::Mount::MOUNT_PARKED:
2649 mountStatus->setStyleSheet(
"font-weight:bold;background-color:red;border:2px solid black;");
2650 if (mountPI->isAnimated())
2651 mountPI->stopAnimation();
2655 if (mountPI->isAnimated())
2656 mountPI->stopAnimation();
2661 {
"status", mountProcess.get()->statusString(
false)}
2664 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2667 void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2686 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2691 capturePreview->updateCaptureStatus(status);
2700 if (focusModule() && focusModule()->
status() == Ekos::FOCUS_COMPLETE)
2701 focusManager->stopAnimation();
2702 m_CountdownTimer.stop();
2705 m_CountdownTimer.start();
2713 {
"status", captureStates[
status]},
2714 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2715 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()}
2718 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2723 capturePreview->updateJobProgress(job, data);
2727 {
"seqv", job->getCompleted()},
2728 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).toInt()},
2729 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2732 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2736 if (data && job->getStatus() == JOB_BUSY)
2741 if (Options::useSummaryPreview())
2742 ekosLiveClient.get()->media()->sendView(m_SummaryView, uuid);
2744 ekosLiveClient.get()->media()->sendData(data, uuid);
2746 if (job->getCoreProperty(SequenceJob::SJ_Preview).toBool() ==
false)
2747 ekosLiveClient.get()->cloud()->upload(data, uuid);
2752 void Manager::updateExposureProgress(Ekos::SequenceJob * job)
2756 {
"expv", job->getExposeLeft()},
2757 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble()}
2760 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2763 void Manager::updateCaptureCountDown()
2765 capturePreview->updateCaptureCountDown(-1);
2769 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2770 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()}
2773 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2777 void Manager::updateFocusStatus(Ekos::FocusState status)
2779 focusManager->updateFocusStatus(status);
2783 {
"status", getFocusStatusString(status,
false)}
2786 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2789 void Manager::updateGuideStatus(Ekos::GuideState status)
2791 guideManager->updateGuideStatus(status);
2794 {
"status", getGuideStatusString(status,
false)}
2797 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2802 mountTarget->setText(o->
name());
2803 ekosLiveClient.get()->message()->updateMountStatus(
QJsonObject({{
"target", o->
name()}}));
2806 void Manager::showEkosOptions()
2808 QWidget * currentWidget = toolsWidget->currentWidget();
2810 if (alignProcess.get() && alignProcess.get() == currentWidget)
2816 alignSettings->
show();
2821 if (guideProcess.get() && guideProcess.get() == currentWidget)
2827 if (ekosOptionsWidget ==
nullptr)
2838 void Manager::getCurrentProfileTelescopeInfo(
double &primaryFocalLength,
double &primaryAperture,
double &guideFocalLength,
2839 double &guideAperture)
2841 ProfileInfo * pi = getCurrentProfile();
2844 int primaryScopeID = 0, guideScopeID = 0;
2845 primaryScopeID = pi->primaryscope;
2846 guideScopeID = pi->guidescope;
2847 if (primaryScopeID > 0 || guideScopeID > 0)
2852 for(
auto oneScope : m_scopeList)
2854 if (oneScope->id().toInt() == primaryScopeID)
2856 primaryFocalLength = oneScope->focalLength();
2857 primaryAperture = oneScope->aperture();
2860 if (oneScope->id().toInt() == guideScopeID)
2862 guideFocalLength = oneScope->focalLength();
2863 guideAperture = oneScope->aperture();
2867 qDeleteAll(m_scopeList);
2872 void Manager::updateDebugInterfaces()
2878 auto debugProp = device->getProperty(
"DEBUG");
2882 auto debugSP = debugProp->getSwitch();
2885 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2886 debugSP->sp[0].s != ISS_ON)
2888 debugSP->at(0)->setState(ISS_ON);
2889 debugSP->at(1)->setState(ISS_OFF);
2890 device->getDriverInfo()->getClientManager()->sendNewSwitch(debugSP);
2891 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
2893 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
2894 debugSP->sp[0].s != ISS_OFF)
2896 debugSP->at(0)->setState(ISS_OFF);
2897 debugSP->at(1)->setState(ISS_ON);
2898 device->getDriverInfo()->getClientManager()->sendNewSwitch(debugSP);
2899 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
2902 if (opsLogs->isINDISettingsChanged())
2903 device->setConfig(SAVE_CONFIG);
2907 void Manager::watchDebugProperty(ISwitchVectorProperty * svp)
2909 if (!strcmp(svp->name,
"DEBUG"))
2914 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
2919 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
2920 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
2922 svp->sp[0].s = ISS_ON;
2923 svp->sp[1].s = ISS_OFF;
2924 deviceInterface->getDriverInfo()->getClientManager()->sendNewSwitch(svp);
2925 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
2931 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
2932 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
2934 svp->sp[0].s = ISS_OFF;
2935 svp->sp[1].s = ISS_ON;
2936 deviceInterface->getDriverInfo()->getClientManager()->sendNewSwitch(svp);
2937 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
2942 void Manager::announceEvent(
const QString &
message, KSNotification::EventType event)
2944 ekosLiveClient.get()->message()->sendEvent(
message, event);
2947 void Manager::connectModules()
2949 DarkLibrary::Instance()->disconnect(
this);
2952 ekosLiveClient.get()->media()->sendData(data,
"+D");
2954 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame);
2957 if (captureProcess.get() && guideProcess.get())
2963 connect(guideProcess.get(), &Ekos::Guide::newStatus, captureProcess.get(), &Ekos::Capture::setGuideStatus,
2969 connect(captureProcess.get(), &Ekos::Capture::newStatus, guideProcess.get(), &Ekos::Guide::setCaptureStatus,
2973 connect(captureProcess.get(), &Ekos::Capture::suspendGuiding, guideProcess.get(), &
Ekos::Guide::suspend,
2975 connect(captureProcess.get(), &Ekos::Capture::resumeGuiding, guideProcess.get(), &
Ekos::Guide::resume,
2977 connect(guideProcess.get(), &Ekos::Guide::guideChipUpdated, captureProcess.get(), &Ekos::Capture::setGuideChip,
2981 connect(captureProcess.get(), &Ekos::Capture::meridianFlipStarted, guideProcess.get(), &
Ekos::Guide::abort,
2983 connect(captureProcess.get(), &Ekos::Capture::meridianFlipCompleted, guideProcess.get(),
2988 if (guideProcess.get() && mountProcess.get())
2999 if (guideProcess.get() && focusProcess.get())
3007 if (captureProcess.get() && focusProcess.get())
3018 connect(captureProcess.get(), &Ekos::Capture::abortFocus, focusProcess.get(), &
Ekos::Focus::abort,
3022 connect(focusProcess.get(), &Ekos::Focus::newStatus, captureProcess.get(), &Ekos::Capture::setFocusStatus,
3026 connect(focusProcess.get(), &Ekos::Focus::newHFR, captureProcess.get(), &Ekos::Capture::setHFR,
Qt::UniqueConnection);
3029 connect(focusProcess.get(), &Ekos::Focus::newFocusTemperatureDelta, captureProcess.get(),
3038 if (captureProcess.get() && alignProcess.get())
3041 connect(alignProcess.get(), &Ekos::Align::newStatus, captureProcess.get(), &Ekos::Capture::setAlignStatus,
3044 connect(alignProcess.get(), &Ekos::Align::newSolverResults, captureProcess.get(), &Ekos::Capture::setAlignResults,
3047 connect(captureProcess.get(), &Ekos::Capture::newStatus, alignProcess.get(), &Ekos::Align::setCaptureStatus,
3052 if (captureProcess.get() && mountProcess.get())
3056 captureProcess->registerNewModule(
"Mount");
3057 mountProcess->registerNewModule(
"Capture");
3064 connect(captureProcess.get(), &Ekos::Capture::newMeridianFlipStatus, mountProcess.get(),
3066 connect(mountProcess.get(), &Ekos::Mount::newMeridianFlipStatus, captureProcess.get(),
3070 connect(mountProcess.get(), &
Ekos::Mount::newStatus, captureProcess.get(), &Ekos::Capture::setMountStatus,
3075 if (captureProcess.get() && ekosLiveClient.get())
3079 connect(captureProcess.get(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3081 connect(captureProcess.get(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3083 connect(captureProcess.get(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3088 if(schedulerProcess.get() && ekosLiveClient.get())
3090 connect(schedulerProcess.get(), &Ekos::Scheduler::jobsUpdated, ekosLiveClient.get()->message(),
3095 if (focusProcess.get() && alignProcess.get())
3097 connect(focusProcess.get(), &Ekos::Focus::newStatus, alignProcess.get(), &Ekos::Align::setFocusStatus,
3102 if (focusProcess.get() && mountProcess.get())
3111 if (mountProcess.get() && alignProcess.get())
3124 if (mountProcess.get() && guideProcess.get())
3126 connect(mountProcess.get(), &Ekos::Mount::pierSideChanged, guideProcess.get(), &Ekos::Guide::setPierSide,
3131 if (alignProcess.get() && ekosLiveClient.get())
3136 connect(alignProcess.get(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3138 connect(alignProcess.get(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3140 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3141 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3143 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3144 ekosLiveClient.get()->message(),
3146 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3147 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3149 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3150 ekosLiveClient.get()->message(),
3152 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3153 ekosLiveClient.get()->message(),
3155 connect(alignProcess.get()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3156 ekosLiveClient.get()->media(),
3159 connect(alignProcess.get(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3161 connect(alignProcess.get(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3164 connect(alignProcess.get(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3167 connect(alignProcess.get(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3172 if (focusProcess.get() && ekosLiveClient.get())
3174 connect(focusProcess.get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3176 connect(focusProcess.get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3181 if (guideProcess.get() && ekosLiveClient.get())
3183 connect(guideProcess.get(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3185 connect(guideProcess.get(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3190 if (analyzeProcess.get())
3192 connect(schedulerProcess.get(), &Ekos::Scheduler::jobStarted,
3194 connect(schedulerProcess.get(), &Ekos::Scheduler::jobEnded,
3196 connect(schedulerProcess.get(), &Ekos::Scheduler::targetDistance,
3199 if (captureProcess.get())
3201 connect(captureProcess.get(), &Ekos::Capture::captureComplete,
3203 connect(captureProcess.get(), &Ekos::Capture::captureStarting,
3205 connect(captureProcess.get(), &Ekos::Capture::captureAborted,
3209 connect(captureProcess.get(), &Ekos::Capture::meridianFlipStarted,
3211 connect(captureProcess.get(), &Ekos::Capture::meridianFlipCompleted,
3215 if (guideProcess.get())
3217 connect(guideProcess.get(), &Ekos::Guide::newStatus,
3220 connect(guideProcess.get(), &Ekos::Guide::guideStats,
3224 if (focusProcess.get())
3226 connect(focusProcess.get(), &Ekos::Focus::autofocusComplete,
3228 connect(focusProcess.get(), &Ekos::Focus::autofocusStarting,
3230 connect(focusProcess.get(), &Ekos::Focus::autofocusAborted,
3232 connect(focusProcess.get(), &Ekos::Focus::newFocusTemperatureDelta,
3235 if (alignProcess.get())
3237 connect(alignProcess.get(), &Ekos::Align::newStatus,
3241 if (mountProcess.get())
3247 connect(mountProcess.get(), &Ekos::Mount::newMeridianFlipStatus,
3252 void Manager::setEkosLiveConnected(
bool enabled)
3254 ekosLiveClient.get()->setConnected(enabled);
3257 void Manager::setEkosLiveConfig(
bool onlineService,
bool rememberCredentials,
bool autoConnect)
3259 ekosLiveClient.get()->setConfig(onlineService, rememberCredentials, autoConnect);
3262 void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3264 ekosLiveClient.get()->setUser(username, password);
3267 bool Manager::ekosLiveStatus()
3269 return ekosLiveClient.get()->isConnected();
3275 for (
auto &oneDevice : m_GenericDevices)
3277 if (oneDevice->getDriverInterface() & interface)
3278 devices.
append(oneDevice);
3284 void Manager::syncActiveDevices()
3286 for (
auto oneDevice : m_GenericDevices)
3290 auto tvp = oneDevice->getBaseDevice()->getText(
"ACTIVE_DEVICES");
3296 for (
auto &it : *tvp)
3299 if (it.isNameMatch(
"ACTIVE_TELESCOPE"))
3301 devs = findDevicesByInterface(INDI::BaseDevice::TELESCOPE_INTERFACE);
3303 else if (it.isNameMatch(
"ACTIVE_DOME"))
3305 devs = findDevicesByInterface(INDI::BaseDevice::DOME_INTERFACE);
3307 else if (it.isNameMatch(
"ACTIVE_GPS"))
3309 devs = findDevicesByInterface(INDI::BaseDevice::GPS_INTERFACE);
3311 else if (it.isNameMatch(
"ACTIVE_ROTATOR"))
3313 devs = findDevicesByInterface(INDI::BaseDevice::ROTATOR_INTERFACE);
3315 else if (it.isNameMatch(
"ACTIVE_FILTER"))
3317 devs = findDevicesByInterface(INDI::BaseDevice::FILTER_INTERFACE);
3319 const QString defaultFilterWheel = Options::defaultCaptureFilterWheel();
3321 if (defaultFilterWheel ==
"--")
3327 oneDevice->getDriverInfo()->getClientManager()->sendNewText(tvp);
3333 for (
auto &oneDev : devs)
3335 if (oneDev->getDeviceName() == defaultFilterWheel)
3338 if (
QString(it.getText()) != defaultFilterWheel)
3341 oneDevice->getDriverInfo()->getClientManager()->sendNewText(tvp);
3359 if (it.getText() != devs.first()->getDeviceName())
3361 it.setText(devs.first()->getDeviceName().toLatin1().constData());
3362 oneDevice->getDriverInfo()->getClientManager()->sendNewText(tvp);
3369 bool Manager::checkUniqueBinaryDriver(
DriverInfo * primaryDriver,
DriverInfo * secondaryDriver)
3371 if (!primaryDriver || !secondaryDriver)
3374 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3375 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3378 void Manager::restartDriver(
const QString &deviceName)
3380 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3383 for (
auto &oneDevice : m_GenericDevices)
3385 if (oneDevice->getDeviceName() == deviceName)
3387 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3393 INDI::WebManager::restartDriver(currentProfile, deviceName);
3396 void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3399 if (name ==
"LOGGING")
3401 Options::setDisableLogging(!enabled);
3405 else if (name ==
"FILE")
3407 Options::setLogToFile(enabled);
3411 else if (name ==
"DEFAULT")
3413 Options::setLogToDefault(enabled);
3418 else if (name ==
"VERBOSE")
3420 Options::setVerboseLogging(enabled);
3424 else if (name ==
"INDI")
3426 Options::setINDILogging(enabled);
3429 else if (name ==
"FITS")
3431 Options::setFITSLogging(enabled);
3434 else if (name ==
"CAPTURE")
3436 Options::setCaptureLogging(enabled);
3437 Options::setINDICCDLogging(enabled);
3438 Options::setINDIFilterWheelLogging(enabled);
3441 else if (name ==
"FOCUS")
3443 Options::setFocusLogging(enabled);
3444 Options::setINDIFocuserLogging(enabled);
3447 else if (name ==
"GUIDE")
3449 Options::setGuideLogging(enabled);
3450 Options::setINDICCDLogging(enabled);
3453 else if (name ==
"ALIGNMENT")
3455 Options::setAlignmentLogging(enabled);
3458 else if (name ==
"MOUNT")
3460 Options::setMountLogging(enabled);
3461 Options::setINDIMountLogging(enabled);
3464 else if (name ==
"SCHEDULER")
3466 Options::setSchedulerLogging(enabled);
3469 else if (name ==
"OBSERVATORY")
3471 Options::setObservatoryLogging(enabled);
3476 void Manager::acceptPortSelection()
3479 m_PortSelector->accept();
3482 void Manager::setPortSelectionComplete()
3484 if (currentProfile->portSelector)
3487 currentProfile->portSelector =
false;
3488 KStarsData::Instance()->
userdb()->SaveProfile(currentProfile);
3491 if (currentProfile->autoConnect)
3495 void Manager::activateModule(
const QString &name,
bool popup)
3497 auto child = toolsWidget->findChild<
QWidget *>(
name);
3500 toolsWidget->setCurrentWidget(child);
3512 if (device->isConnected())
3514 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3521 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3527 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3529 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3536 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3542 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3547 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3551 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3558 void Manager::setDeviceReady()
3562 if (device->isConnected())
3563 createModules(device);
3566 else if (currentProfile->autoConnect && currentProfile->portSelector ==
false)