12#include "profileinfo.h"
13#include "indi/drivermanager.h"
14#include "indi/indilistener.h"
15#include "auxiliary/ksmessagebox.h"
16#include "ekos/auxiliary/filtermanager.h"
17#include "ekos/auxiliary/opticaltrainmanager.h"
18#include "ekos/auxiliary/profilesettings.h"
19#include "ekos/capture/capture.h"
20#include "ekos/focus/focusmodule.h"
21#include "ekos/guide/guide.h"
22#include "ekos/mount/mount.h"
23#include "ekos/scheduler/scheduler.h"
24#include "ekos/scheduler/schedulermodulestate.h"
27#include "kstarsdata.h"
28#include "ekos_debug.h"
30#include "skymapcomposite.h"
31#include "catalogobject.h"
32#include "fitsviewer/fitsviewer.h"
33#include "fitsviewer/fitstab.h"
34#include "ekos/auxiliary/darklibrary.h"
39#include <KActionCollection>
40#include <basedevice.h>
47 m_Manager(manager), m_NodeManagers(nodeManagers), m_DSOManager(CatalogsDB::dso_db_path())
49 for (
auto &nodeManager : m_NodeManagers)
51 connect(nodeManager->message(), &Node::connected,
this, &Message::onConnected);
52 connect(nodeManager->message(), &Node::disconnected,
this, &Message::onDisconnected);
53 connect(nodeManager->message(), &Node::onTextReceived,
this, &Message::onTextReceived);
56 connect(manager, &Ekos::Manager::newModule,
this, &Message::sendModuleState);
60 m_PendingPropertiesTimer.setInterval(500);
63 m_DebouncedSend.setInterval(500);
70void Message::onConnected()
72 auto node = qobject_cast<Node*>(sender());
76 qCInfo(KSTARS_EKOS) <<
"Connected to Message Websocket server at" << node->url().toDisplayString();
78 m_PendingPropertiesTimer.start();
87void Message::onDisconnected()
89 auto node = qobject_cast<Node*>(sender());
93 qCInfo(KSTARS_EKOS) <<
"Disconnected from Message Websocket server at" << node->url().toDisplayString();
95 if (isConnected() ==
false)
97 m_PendingPropertiesTimer.stop();
105void Message::onTextReceived(
const QString &message)
107 auto node = qobject_cast<Node*>(sender());
108 if (!node || message.
isEmpty())
111 qCInfo(KSTARS_EKOS) <<
"Websocket Message" << message;
116 qCWarning(KSTARS_EKOS) <<
"Ekos Live Parsing Error" <<
error.errorString();
121 const QString command = msgObj[
"type"].toString();
122 const QJsonObject payload = msgObj[
"payload"].toObject();
124 if (command == commands[GET_CONNECTION])
128 else if (command == commands[LOGOUT] || command == commands[SESSION_EXPIRED])
130 emit expired(node->url());
133 else if (command == commands[SET_CLIENT_STATE])
136 if (payload[
"state"].toBool(
false))
138 qCInfo(KSTARS_EKOS) <<
"EkosLive client is connected.";
141 if (KStarsData::Instance()->clock()->isActive() ==
false)
143 qCInfo(KSTARS_EKOS) <<
"Resuming and syncing clock.";
154 qCInfo(KSTARS_EKOS) <<
"EkosLive client is disconnected.";
156 if (
KStars::Instance()->isStartedWithClockRunning() ==
false && m_Manager->ekosStatus() == Ekos::CommunicationStatus::Idle)
158 qCInfo(KSTARS_EKOS) <<
"Stopping the clock.";
163 else if (command == commands[GET_DRIVERS])
165 else if (command == commands[GET_PROFILES])
167 else if (command == commands[GET_SCOPES])
169 else if (command == commands[GET_DSLR_LENSES])
171 else if(command == commands[INVOKE_METHOD])
173 auto object = findObject(payload[
"object"].
toString());
175 invokeMethod(
object, payload);
177 else if(command == commands[SET_PROPERTY])
179 auto object = findObject(payload[
"object"].
toString());
181 object->setProperty(payload[
"name"].
toString().toLatin1().constData(), payload[
"value"].toVariant());
183 else if(command == commands[GET_PROPERTY])
185 auto map = QVariantMap();
186 map[
"result"] =
false;
187 auto object = findObject(payload[
"object"].
toString());
190 auto value =
object->property(payload[
"name"].
toString().toLatin1().constData());
193 map[
"result"] =
true;
194 map[
"value"] = value;
199 else if (command == commands[TRAIN_GET_ALL])
201 else if (command == commands[TRAIN_SETTINGS_GET])
203 auto id = payload[
"id"].toInt(-1);
207 auto settings = Ekos::OpticalTrainSettings::Instance()->getSettings();
208 if (!settings.isEmpty())
213 processScopeCommands(command, payload);
215 processProfileCommands(command, payload);
217 processAstronomyCommands(command, payload);
218 else if (command == commands[DIALOG_GET_RESPONSE])
219 processDialogResponse(payload);
221 processOptionsCommands(command, payload);
223 processSchedulerCommands(command, payload);
225 processDSLRCommands(command, payload);
227 processFileCommands(command, payload);
229 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
232 if (command == commands[GET_STATES])
234 else if (command == commands[GET_STELLARSOLVER_PROFILES])
235 sendStellarSolverProfiles();
236 else if (command == commands[GET_DEVICES])
239 processCaptureCommands(command, payload);
241 processMountCommands(command, payload);
243 processFocusCommands(command, payload);
245 processGuideCommands(command, payload);
247 processAlignCommands(command, payload);
249 processPolarCommands(command, payload);
251 processTrainCommands(command, payload);
253 processFilterManagerCommands(command, payload);
255 processDarkLibraryCommands(command, payload);
257 processDeviceCommands(command, payload);
264bool Message::isConnected()
const
266 return std::any_of(m_NodeManagers.begin(), m_NodeManagers.end(), [](
auto & nodeManager)
268 return nodeManager->message()->isConnected();
275void Message::sendStellarSolverProfiles()
277 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
282 if (m_Manager->focusModule())
287 if (m_Manager->alignModule())
291 sendResponse(commands[GET_STELLARSOLVER_PROFILES], profiles);
297void Message::sendDrivers()
299 sendResponse(commands[GET_DRIVERS], DriverManager::Instance()->getDriverList());
305void Message::sendDevices()
307 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
312 for(
auto &gd : INDIListener::devices())
316 {
"name", gd->getDeviceName()},
317 {
"connected", gd->isConnected()},
318 {
"version", gd->getDriverVersion()},
319 {
"interface",
static_cast<int>(gd->getDriverInterface())},
322 deviceList.
append(oneDevice);
325 sendResponse(commands[GET_DEVICES], deviceList);
331void Message::sendTrains()
335 for(
auto &train : Ekos::OpticalTrainManager::Instance()->getOpticalTrains())
338 sendResponse(commands[TRAIN_GET_ALL], trains);
344void Message::sendTrainProfiles()
346 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
349 auto profiles = Ekos::ProfileSettings::Instance()->getSettings();
357void Message::requestOpticalTrains(
bool show)
359 sendResponse(commands[TRAIN_CONFIGURATION_REQUESTED], show);
365void Message::sendScopes()
372 for (
auto &scope : allScopes)
373 scopeList.
append(scope->toJson());
375 sendResponse(commands[GET_SCOPES], scopeList);
381void Message::sendDSLRLenses()
388 for (
auto &dslrLens : allDslrLens)
389 dslrList.
append(dslrLens->toJson());
391 sendResponse(commands[GET_DSLR_LENSES], dslrList);
397void Message::sendTemperature(
double value)
405 {
"name", oneCCD->getDeviceName()},
406 {
"temperature", value}
409 sendResponse(commands[NEW_CAMERA_STATE], temperature);
416void Message::processCaptureCommands(
const QString &command,
const QJsonObject &payload)
418 auto capture = m_Manager->captureModule();
420 if (capture ==
nullptr)
422 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as capture module is not available";
426 if (command == commands[CAPTURE_PREVIEW])
428 capture->mainCamera()->capturePreview();
430 else if (command == commands[CAPTURE_TOGGLE_VIDEO])
432 capture->setVideoLimits(payload[
"maxBufferSize"].toInt(512), payload[
"maxPreviewFPS"].toInt(10));
433 capture->toggleVideo(payload[
"enabled"].toBool());
435 else if (command == commands[CAPTURE_START])
437 else if (command == commands[CAPTURE_STOP])
439 else if (command == commands[CAPTURE_LOOP])
441 capture->mainCamera()->startFraming();
443 else if (command == commands[CAPTURE_GET_SEQUENCES])
445 sendCaptureSequence(capture->getSequence());
447 else if (command == commands[CAPTURE_ADD_SEQUENCE])
450 capture->mainCamera()->createJob();
452 else if (command == commands[CAPTURE_REMOVE_SEQUENCE])
454 if (capture->mainCamera()->removeJob(payload[
"index"].toInt()) ==
false)
455 sendCaptureSequence(capture->getSequence());
457 else if (command == commands[CAPTURE_CLEAR_SEQUENCES])
459 capture->clearSequenceQueue();
461 else if (command == commands[CAPTURE_SAVE_SEQUENCE_FILE])
463 if (capture->saveSequenceQueue(payload[
"filepath"].toString()))
466 else if (command == commands[CAPTURE_LOAD_SEQUENCE_FILE])
481 path = payload[
"filepath"].toString();
485 auto result = capture->loadSequenceQueue(path);
491 sendResponse(commands[CAPTURE_LOAD_SEQUENCE_FILE], response);
494 else if (command == commands[CAPTURE_GET_ALL_SETTINGS])
496 sendCaptureSettings(capture->mainCamera()->getAllSettings());
498 else if (command == commands[CAPTURE_SET_ALL_SETTINGS])
501 capture->mainCamera()->setAllSettings(settings);
502 KSUtils::setGlobalSettings(settings);
504 else if (command == commands[CAPTURE_GENERATE_DARK_FLATS])
506 capture->mainCamera()->generateDarkFlats();
513void Message::sendCaptureSequence(
const QJsonArray &sequenceArray)
515 sendResponse(commands[CAPTURE_GET_SEQUENCES], sequenceArray);
518void Message::sendPreviewLabel(
const QString &preview)
524 sendResponse(commands[CAPTURE_GET_PREVIEW_LABEL], payload);
530void Message::sendCaptureSettings(
const QVariantMap &settings)
532 m_DebouncedSend.start();
533 m_DebouncedMap[commands[CAPTURE_GET_ALL_SETTINGS]] = settings;
539void Message::sendAlignSettings(
const QVariantMap &settings)
541 m_DebouncedSend.start();
542 m_DebouncedMap[commands[ALIGN_GET_ALL_SETTINGS]] = settings;
548void Message::sendGuideSettings(
const QVariantMap &settings)
550 m_DebouncedSend.start();
551 m_DebouncedMap[commands[GUIDE_GET_ALL_SETTINGS]] = settings;
558void Message::sendFocusSettings(
const QVariantMap &settings)
560 m_DebouncedSend.start();
561 m_DebouncedMap[commands[FOCUS_GET_ALL_SETTINGS]] = settings;
567void Message::sendMountSettings(
const QVariantMap &settings)
569 m_DebouncedSend.start();
570 m_DebouncedMap[commands[MOUNT_GET_ALL_SETTINGS]] = settings;
576void Message::sendDarkLibrarySettings(
const QVariantMap &settings)
578 m_DebouncedSend.start();
579 m_DebouncedMap[commands[DARK_LIBRARY_GET_ALL_SETTINGS]] = settings;
586void Message::sendSchedulerSettings(
const QVariantMap &settings)
588 m_DebouncedSend.start();
589 m_DebouncedMap[commands[SCHEDULER_GET_ALL_SETTINGS]] = settings;
595void Message::dispatchDebounceQueue()
603 m_DebouncedMap.clear();
606 Options::self()->save();
616 if (guide ==
nullptr)
618 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as guide module is not available";
622 if (command == commands[GUIDE_START])
626 else if (command == commands[GUIDE_CAPTURE])
628 else if (command == commands[GUIDE_LOOP])
630 else if (command == commands[GUIDE_STOP])
632 else if (command == commands[GUIDE_CLEAR])
634 else if (command == commands[GUIDE_SET_ALL_SETTINGS])
637 guide->setAllSettings(settings);
638 KSUtils::setGlobalSettings(settings);
640 else if (command == commands[GUIDE_GET_ALL_SETTINGS])
641 sendGuideSettings(guide->getAllSettings());
642 else if(command == commands[GUIDE_SET_CALIBRATION_SETTINGS])
645 Options::setCalibrationPulseDuration(payload[
"pulse"].toInt());
646 Options::setGuideCalibrationBacklash(payload[
"max_move"].toInt());
647 Options::setTwoAxisEnabled(payload[
"two_axis"].toBool());
648 Options::setGuideAutoSquareSizeEnabled(payload[
"square_size"].toBool());
649 Options::setGuideCalibrationBacklash(payload[
"calibrationBacklash"].toBool());
650 Options::setResetGuideCalibration(payload[
"resetCalibration"].toBool());
651 Options::setReuseGuideCalibration(payload[
"reuseCalibration"].toBool());
652 Options::setReverseDecOnPierSideChange(payload[
"reverseCalibration"].toBool());
653 sendGuideSettings(m_Manager->guideModule()->getAllSettings());
663 if (m_Manager->focusModule())
664 focus = m_Manager->focusModule()->mainFocuser();
668 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as focus module is not available";
672 if (command == commands[FOCUS_START])
674 else if (command == commands[FOCUS_CAPTURE])
679 else if (command == commands[FOCUS_STOP])
681 else if (command == commands[FOCUS_RESET])
683 else if (command == commands[FOCUS_IN])
684 focus->focusIn(payload[
"steps"].toInt());
685 else if (command == commands[FOCUS_OUT])
686 focus->focusOut(payload[
"steps"].toInt());
687 else if (command == commands[FOCUS_LOOP])
688 focus->startFraming();
689 else if (command == commands[FOCUS_SET_ALL_SETTINGS])
692 focus->setAllSettings(settings);
693 KSUtils::setGlobalSettings(settings);
696 else if (command == commands[FOCUS_GET_ALL_SETTINGS])
697 sendFocusSettings(focus->getAllSettings());
698 else if (command == commands[FOCUS_SET_CROSSHAIR])
700 double x = payload[
"x"].toDouble();
701 double y = payload[
"y"].toDouble();
702 focus->selectFocusStarFraction(x, y);
713 if (mount ==
nullptr)
715 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as mount module is not available";
719 if (command == commands[MOUNT_ABORT])
721 else if (command == commands[MOUNT_PARK])
723 else if (command == commands[MOUNT_UNPARK])
725 else if (command == commands[MOUNT_SET_TRACKING])
726 mount->setTrackEnabled(payload[
"enabled"].toBool());
727 else if (command == commands[MOUNT_SYNC_RADE])
729 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
732 mount->sync(ra.Hours(), de.Degrees());
734 else if (command == commands[MOUNT_SYNC_TARGET])
738 else if (command == commands[MOUNT_GOTO_RADE])
740 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
743 mount->slew(ra.Hours(), de.Degrees());
745 else if (command == commands[MOUNT_GOTO_TARGET])
749 else if (command == commands[MOUNT_SET_SLEW_RATE])
751 int rate = payload[
"rate"].toInt(-1);
753 mount->setSlewRate(rate);
755 else if (command == commands[MOUNT_SET_ALL_SETTINGS])
758 mount->setAllSettings(settings);
759 KSUtils::setGlobalSettings(settings);
761 else if (command == commands[MOUNT_GET_ALL_SETTINGS])
762 sendMountSettings(
mount->getAllSettings());
763 else if (command == commands[MOUNT_SET_MOTION])
765 QString direction = payload[
"direction"].toString();
766 ISD::Mount::MotionCommand action = payload[
"action"].toBool(
false) ?
767 ISD::Mount::MOTION_START : ISD::Mount::MOTION_STOP;
769 if (direction ==
"N")
770 mount->motionCommand(action, ISD::Mount::MOTION_NORTH, -1);
771 else if (direction ==
"S")
772 mount->motionCommand(action, ISD::Mount::MOTION_SOUTH, -1);
773 else if (direction ==
"E")
774 mount->motionCommand(action, -1, ISD::Mount::MOTION_EAST);
775 else if (direction ==
"W")
776 mount->motionCommand(action, -1, ISD::Mount::MOTION_WEST);
778 else if (command == commands[MOUNT_GOTO_PIXEL])
780 const auto name = payload[
"camera"].toString();
781 const auto xFactor = payload[
"x"].toDouble();
782 const auto yFactor = payload[
"y"].toDouble();
784 for(
auto &oneDevice : INDIListener::devices())
786 auto camera = oneDevice->getCamera();
787 if (!camera || camera->getDeviceName() != name)
790 auto primaryChip = camera->getChip(ISD::CameraChip::PRIMARY_CCD);
795 auto imageData = primaryChip->getImageData();
796 if (!imageData || imageData->hasWCS() ==
false)
799 auto x = xFactor * imageData->width();
800 auto y = yFactor * imageData->height();
804 if (imageData->pixelToWCS(point, coord))
808 mount->gotoTarget(coord);
813 else if (command == commands[MOUNT_TOGGLE_AUTOPARK])
814 mount->setAutoParkEnabled(payload[
"toggled"].toBool());
824 if (align ==
nullptr)
826 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as align module is not available";
830 if (command == commands[ALIGN_SOLVE])
834 else if (command == commands[ALIGN_SET_ALL_SETTINGS])
837 align->setAllSettings(settings);
838 KSUtils::setGlobalSettings(settings);
840 else if (command == commands[ALIGN_GET_ALL_SETTINGS])
841 sendAlignSettings(align->getAllSettings());
842 else if(command == commands[ALIGN_SET_ASTROMETRY_SETTINGS])
844 Options::setAstrometryRotatorThreshold(payload[
"threshold"].toInt());
845 Options::setAstrometryUseRotator(payload[
"rotator_control"].toBool());
846 Options::setAstrometryUseImageScale(payload[
"scale"].toBool());
847 Options::setAstrometryUsePosition(payload[
"position"].toBool());
849 else if (command == commands[ALIGN_STOP])
851 else if (command == commands[ALIGN_LOAD_AND_SLEW])
870 else if (command == commands[ALIGN_MANUAL_ROTATOR_TOGGLE])
872 align->toggleManualRotator(payload[
"toggled"].toBool());
881 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
889 sendResponse(commands[NEW_ALIGN_STATE], alignState);
895void Message::setAlignSolution(
const QVariantMap &solution)
897 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
905 sendResponse(commands[NEW_ALIGN_STATE], alignState);
911void Message::processSchedulerCommands(
const QString &command,
const QJsonObject &payload)
915 if (command == commands[SCHEDULER_GET_JOBS])
919 else if (command == commands[SCHEDULER_ADD_JOBS])
923 else if(command == commands[SCHEDULER_REMOVE_JOBS])
925 int index = payload[
"index"].toInt();
928 else if(command == commands[SCHEDULER_GET_ALL_SETTINGS])
930 sendSchedulerSettings(scheduler->getAllSettings());
932 else if(command == commands[SCHEDULER_SET_ALL_SETTINGS])
935 scheduler->setAllSettings(settings);
936 KSUtils::setGlobalSettings(settings);
938 else if (command == commands[SCHEDULER_SAVE_FILE])
943 else if (command == commands[SCHEDULER_SAVE_SEQUENCE_FILE])
964 sendResponse(commands[SCHEDULER_SAVE_SEQUENCE_FILE], response);
966 else if (command == commands[SCHEDULER_LOAD_FILE])
981 path = payload[
"filepath"].toString();
991 sendResponse(commands[SCHEDULER_LOAD_FILE], response);
994 else if(command == commands[SCHEDULER_START_JOB])
996 scheduler->toggleScheduler();
998 else if(command == commands[SCHEDULER_IMPORT_MOSAIC])
1001 sendSchedulerJobs();
1003 sendEvent(
i18n(
"Mosaic import failed."), KSNotification::Scheduler, KSNotification::Alert);
1010void Message::processPolarCommands(
const QString &command,
const QJsonObject &payload)
1018 if (command == commands[PAH_START])
1020 paa->startPAHProcess();
1022 if (command == commands[PAH_STOP])
1024 paa->stopPAHProcess();
1026 else if (command == commands[PAH_REFRESH])
1028 paa->setPAHRefreshDuration(payload[
"value"].toDouble(1));
1029 paa->startPAHRefreshProcess();
1031 else if (command == commands[PAH_SET_ALGORITHM])
1035 algorithmCombo->
setCurrentIndex(
static_cast<Ekos::PolarAlignmentAssistant::RefreshAlgorithm
>(payload[
"value"].toInt(1)));
1037 else if (command == commands[PAH_RESET_VIEW])
1039 emit resetPolarView();
1041 else if (command == commands[PAH_SET_CROSSHAIR])
1043 double x = payload[
"x"].toDouble();
1044 double y = payload[
"y"].toDouble();
1046 if (m_BoundingRect.isNull() ==
false)
1050 double boundX = x * m_BoundingRect.width();
1051 double boundY = y * m_BoundingRect.height();
1056 x = ((boundX + m_BoundingRect.x()) / (m_CurrentZoom / 100)) / m_ViewSize.width();
1057 y = ((boundY + m_BoundingRect.y()) / (m_CurrentZoom / 100)) / m_ViewSize.height();
1061 paa->setPAHCorrectionOffsetPercentage(x, y);
1063 else if (command == commands[PAH_SELECT_STAR_DONE])
1069 else if (command == commands[PAH_REFRESHING_DONE])
1071 paa->stopPAHProcess();
1073 else if (command == commands[PAH_SLEW_DONE])
1075 paa->setPAHSlewDone();
1077 else if (command == commands[PAH_PAH_SET_ZOOM])
1079 double scale = payload[
"scale"].toDouble();
1080 align->setAlignZoom(scale);
1088void Message::setPAHStage(Ekos::PolarAlignmentAssistant::Stage stage)
1090 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1103 {
"stage", paa->getPAHStageString(
false)}
1108 if (stage == Ekos::PolarAlignmentAssistant::PAH_STAR_SELECT)
1109 align->zoomAlignView();
1111 sendResponse(commands[NEW_POLAR_STATE], polarState);
1117void Message::setPAHMessage(
const QString &message)
1119 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1129 sendResponse(commands[NEW_POLAR_STATE], polarState);
1135void Message::setPolarResults(
QLineF correctionVector,
double polarError,
double azError,
double altError)
1137 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1140 this->correctionVector = correctionVector;
1145 {
"center_x",
center.x()},
1146 {
"center_y",
center.y()},
1147 {
"mag", correctionVector.
length()},
1148 {
"pa", correctionVector.
angle()},
1149 {
"error", polarError},
1150 {
"azError", azError},
1151 {
"altError", altError}
1159 sendResponse(commands[NEW_POLAR_STATE], polarState);
1165void Message::setUpdatedErrors(
double total,
double az,
double alt)
1167 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1172 {
"updatedError", total},
1173 {
"updatedAZError", az},
1174 {
"updatedALTError", alt}
1177 sendResponse(commands[NEW_POLAR_STATE], error);
1183void Message::setPAHEnabled(
bool enabled)
1185 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
1190 {
"enabled", enabled}
1193 sendResponse(commands[NEW_POLAR_STATE], polarState);
1199void Message::processProfileCommands(
const QString &command,
const QJsonObject &payload)
1201 if (command == commands[START_PROFILE])
1203 if (m_Manager->getEkosStartingStatus() != Ekos::Idle)
1206 m_Manager->setProfile(payload[
"name"].
toString());
1211 else if (command == commands[STOP_PROFILE])
1218 m_PropertySubscriptions.clear();
1220 else if (command == commands[ADD_PROFILE])
1222 m_Manager->addNamedProfile(payload);
1225 else if (command == commands[UPDATE_PROFILE])
1227 m_Manager->editNamedProfile(payload);
1230 else if (command == commands[GET_PROFILE])
1232 m_Manager->getNamedProfile(payload[
"name"].
toString());
1234 else if (command == commands[DELETE_PROFILE])
1236 m_Manager->deleteNamedProfile(payload[
"name"].
toString());
1239 else if (command == commands[SET_PROFILE_MAPPING])
1241 m_Manager->setProfileMapping(payload);
1243 else if (command == commands[SET_PROFILE_PORT_SELECTION])
1245 requestPortSelection(
false);
1246 m_Manager->acceptPortSelection();
1253void Message::sendProfiles()
1258 if (!m_Manager->getCurrentProfile(profile))
1261 for (
auto &oneProfile : m_Manager->profiles)
1262 profileArray.
append(oneProfile->toJson());
1266 {
"selectedProfile", profile->name},
1267 {
"profiles", profileArray}
1269 sendResponse(commands[GET_PROFILES], profiles);
1275void Message::sendSchedulerJobs()
1279 {
"jobs", m_Manager->schedulerModule()->moduleState()->getJSONJobs()}
1281 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1287void Message::sendSchedulerJobList(
QJsonArray jobsList)
1293 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1299void Message::sendSchedulerStatus(
const QJsonObject &status)
1301 sendResponse(commands[NEW_SCHEDULER_STATE], status);
1308void Message::setEkosStatingStatus(Ekos::CommunicationStatus status)
1310 if (status == Ekos::Pending)
1315 {
"connected",
true},
1316 {
"online",
status == Ekos::Success}
1318 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
1324void Message::setINDIStatus(Ekos::CommunicationStatus status)
1331 sendResponse(commands[NEW_INDI_STATE], connectionState);
1337void Message::processOptionsCommands(
const QString &command,
const QJsonObject &payload)
1339 if (command == commands[OPTION_SET])
1341 const QJsonArray options = payload[
"options"].toArray();
1342 for (
const auto &oneOption : options)
1343 Options::self()->setProperty(oneOption[
QString(
"name")].
toString().toLatin1(), oneOption[
QString(
"value")].toVariant());
1345 Options::self()->save();
1346 emit optionsUpdated();
1348 else if (command == commands[OPTION_GET])
1352 for (
const auto &oneOption : options)
1354 const auto name = oneOption[
QString(
"name")].toString();
1358 map[
"value"] = value;
1361 sendResponse(commands[OPTION_GET], result);
1368void Message::processScopeCommands(
const QString &command,
const QJsonObject &payload)
1370 if (command == commands[ADD_SCOPE])
1373 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble());
1375 else if (command == commands[UPDATE_SCOPE])
1378 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble(), payload[
"id"].
toString());
1380 else if (command == commands[DELETE_SCOPE])
1393 if (command == commands[DSLR_SET_INFO])
1395 if (m_Manager->captureModule())
1396 m_Manager->captureModule()->mainCamera()->addDSLRInfo(
1398 payload[
"width"].toInt(),
1399 payload[
"height"].toInt(),
1400 payload[
"pixelw"].toDouble(),
1401 payload[
"pixelh"].toDouble());
1404 else if(command == commands[DSLR_ADD_LENS])
1407 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble());
1409 else if (command == commands[DSLR_DELETE_LENS])
1413 else if (command == commands[DSLR_UPDATE_LENS])
1416 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble(), payload[
"id"].
toString());
1425void Message::processTrainCommands(
const QString &command,
const QJsonObject &payload)
1427 if (command == commands[TRAIN_GET_PROFILES])
1428 sendTrainProfiles();
1429 else if (command == commands[TRAIN_SET])
1431 auto module = payload["module"].toString();
1432 auto name = payload[
"name"].toString();
1434 if (module ==
"capture")
1436 if (m_Manager->captureModule())
1437 m_Manager->captureModule()->setOpticalTrain(name);
1439 else if (module ==
"focus")
1441 if (m_Manager->focusModule())
1442 m_Manager->focusModule()->mainFocuser()->setOpticalTrain(name);
1444 else if (module ==
"guide")
1446 if (m_Manager->guideModule())
1447 m_Manager->guideModule()->setOpticalTrain(name);
1449 else if (module ==
"align")
1451 if (m_Manager->alignModule())
1452 m_Manager->alignModule()->setOpticalTrain(name);
1454 else if (module ==
"mount")
1456 if (m_Manager->mountModule())
1457 m_Manager->mountModule()->setOpticalTrain(name);
1459 else if (module ==
"darklibrary")
1461 Ekos::DarkLibrary::Instance()->setOpticalTrain(name);
1464 else if (command == commands[TRAIN_ADD])
1466 Ekos::OpticalTrainManager::Instance()->addOpticalTrain(payload);
1468 else if (command == commands[TRAIN_UPDATE])
1470 Ekos::OpticalTrainManager::Instance()->setOpticalTrain(payload);
1472 else if (command == commands[TRAIN_DELETE])
1474 Ekos::OpticalTrainManager::Instance()->removeOpticalTrain(payload[
"name"].
toString());
1476 else if (command == commands[TRAIN_RESET])
1478 Ekos::OpticalTrainManager::Instance()->reset();
1480 else if (command == commands[TRAIN_ACCEPT])
1482 requestOpticalTrains(
false);
1483 Ekos::OpticalTrainManager::Instance()->
accept();
1491void Message::processFilterManagerCommands(
const QString &command,
const QJsonObject &payload)
1494 if (m_Manager->captureModule())
1495 manager = m_Manager->captureModule()->mainCamera()->filterManager();
1500 if (command == commands[FM_GET_DATA])
1503 sendResponse(commands[FM_GET_DATA], data);
1505 else if (command == commands[FM_SET_DATA])
1507 manager->setFilterData(payload);
1514void Message::processDarkLibraryCommands(
const QString &command,
const QJsonObject &payload)
1516 if (command == commands[DARK_LIBRARY_START])
1517 Ekos::DarkLibrary::Instance()->start();
1518 else if(command == commands[DARK_LIBRARY_SET_ALL_SETTINGS])
1521 Ekos::DarkLibrary::Instance()->setAllSettings(settings);
1522 KSUtils::setGlobalSettings(settings);
1524 else if(command == commands[DARK_LIBRARY_GET_ALL_SETTINGS])
1525 sendDarkLibrarySettings(Ekos::DarkLibrary::Instance()->getAllSettings());
1526 else if(command == commands[DARK_LIBRARY_GET_DEFECT_SETTINGS])
1527 sendResponse(commands[DARK_LIBRARY_GET_DEFECT_SETTINGS], Ekos::DarkLibrary::Instance()->getDefectSettings());
1528 else if(command == commands[DARK_LIBRARY_SET_CAMERA_PRESETS])
1530 Ekos::DarkLibrary::Instance()->setCameraPresets(payload);
1532 else if (command == commands[DARK_LIBRARY_STOP])
1534 Ekos::DarkLibrary::Instance()->
stop();
1536 else if (command == commands[DARK_LIBRARY_GET_MASTERS_IMAGE])
1538 const int row = payload[
"row"].toInt();
1539 Ekos::DarkLibrary::Instance()->loadIndexInView(row);
1541 else if (command == commands[DARK_LIBRARY_GET_CAMERA_PRESETS])
1543 sendResponse(commands[DARK_LIBRARY_GET_CAMERA_PRESETS], Ekos::DarkLibrary::Instance()->getCameraPresets());
1545 else if (command == commands[DARK_LIBRARY_SET_DEFECT_PIXELS])
1547 Ekos::DarkLibrary::Instance()->setDefectPixels(payload);
1549 else if (command == commands[DARK_LIBRARY_SAVE_MAP])
1551 Ekos::DarkLibrary::Instance()->saveMapB->click();
1553 else if (command == commands[DARK_LIBRARY_SET_DEFECT_FRAME])
1555 Ekos::DarkLibrary::Instance()->setDefectMapEnabled(
false);
1557 else if (command == commands[DARK_LIBRARY_GET_VIEW_MASTERS])
1559 sendResponse(commands[DARK_LIBRARY_GET_VIEW_MASTERS], Ekos::DarkLibrary::Instance()->getViewMasters());
1561 else if (command == commands[DARK_LIBRARY_CLEAR_MASTERS_ROW])
1563 const int rowIndex = payload[
"row"].toInt();
1564 Ekos::DarkLibrary::Instance()->clearRow(rowIndex);
1571void Message::processDeviceCommands(
const QString &command,
const QJsonObject &payload)
1573 QString device = payload[
"device"].toString();
1576 if (device.
isEmpty() && command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1578 m_PropertySubscriptions.clear();
1583 if (!INDIListener::findDevice(device, oneDevice))
1587 if (command == commands[DEVICE_PROPERTY_GET])
1590 if (oneDevice->getJSONProperty(payload[
"property"].toString(), propObject, payload[
"compact"].toBool(
true)))
1591 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
1594 else if (command == commands[DEVICE_PROPERTY_SET])
1596 oneDevice->setJSONProperty(payload[
"property"].
toString(), payload[
"elements"].toArray());
1599 else if (command == commands[DEVICE_GET])
1602 for (
const auto &oneProp : *oneDevice->getProperties())
1605 if (oneDevice->getJSONProperty(oneProp.getName(), singleProp, payload[
"compact"].toBool(
false)))
1615 sendResponse(commands[DEVICE_GET], response);
1619 else if (command == commands[DEVICE_PROPERTY_SUBSCRIBE])
1622 const QJsonArray groups = payload[
"groups"].toArray();
1626 if (m_PropertySubscriptions.contains(device))
1627 props = m_PropertySubscriptions[device];
1632 for (
const auto &oneProp : properties)
1633 props.
insert(oneProp.toString());
1636 else if (groups.
isEmpty() ==
false)
1639 for (
auto &oneProp : *oneDevice->getProperties())
1641 if (indiGroups.contains(oneProp.getGroupName()))
1642 props.
insert(oneProp.getName());
1648 for (
auto &oneProp : *oneDevice->getProperties())
1649 props.
insert(oneProp.getName());
1652 m_PropertySubscriptions[device] = props;
1654 else if (command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1657 const QJsonArray groups = payload[
"groups"].toArray();
1661 if (m_PropertySubscriptions.contains(device))
1662 props = m_PropertySubscriptions[device];
1668 for (
const auto &oneProp : properties)
1669 props.
remove(oneProp.toString());
1672 else if (groups.
isEmpty() ==
false)
1675 for (
auto &oneProp : *oneDevice->getProperties())
1677 if (indiGroups.contains(oneProp.getGroupName()))
1678 props.
remove(oneProp.getName());
1684 for (
auto &oneProp : *oneDevice->getProperties())
1685 props.
remove(oneProp.getName());
1688 m_PropertySubscriptions[device] = props;
1695void Message::processAstronomyCommands(
const QString &command,
const QJsonObject &payload)
1697 if (command == commands[ASTRO_GET_ALMANC])
1704 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
1708 {
"SunRise", almanac.getSunRise()},
1709 {
"SunSet", almanac.getSunSet()},
1710 {
"SunMaxAlt", almanac.getSunMaxAlt()},
1711 {
"SunMinAlt", almanac.getSunMinAlt()},
1712 {
"MoonRise", almanac.getMoonRise()},
1713 {
"MoonSet", almanac.getMoonSet()},
1714 {
"MoonPhase", almanac.getMoonPhase()},
1715 {
"MoonIllum", almanac.getMoonIllum()},
1716 {
"Dawn", almanac.getDawnAstronomicalTwilight()},
1717 {
"Dusk", almanac.getDuskAstronomicalTwilight()},
1721 sendResponse(commands[ASTRO_GET_ALMANC], response);
1723 else if (command == commands[ASTRO_GET_NAMES])
1725 auto composite = KStarsData::Instance()->
skyComposite();
1728 CatalogsDB::CatalogObjectList dsoObjects;
1730 allObjects.
append(composite->objectLists(SkyObject::STAR));
1731 allObjects.
append(composite->objectLists(SkyObject::CATALOG_STAR));
1732 allObjects.
append(composite->objectLists(SkyObject::PLANET));
1733 allObjects.
append(composite->objectLists(SkyObject::MOON));
1734 allObjects.
append(composite->objectLists(SkyObject::COMET));
1735 allObjects.
append(composite->objectLists(SkyObject::ASTEROID));
1736 allObjects.
append(composite->objectLists(SkyObject::SUPERNOVA));
1737 allObjects.
append(composite->objectLists(SkyObject::SATELLITE));
1738 dsoObjects = m_DSOManager.get_objects_all();
1740 for (
auto &oneObject : allObjects)
1741 all << oneObject.second->name() << oneObject.second->longname().split(
", ");
1743 for (
auto &oneObject : dsoObjects)
1744 all << oneObject.name() << oneObject.longname().split(
", ");
1750 else if (command == commands[ASTRO_GET_DESIGNATIONS])
1754 for (
auto &oneObject : m_DSOManager.get_objects_all())
1758 {
"primary", oneObject.name()},
1762 designations.
append(oneDesignation);
1765 sendResponse(commands[ASTRO_GET_DESIGNATIONS], designations);
1767 else if (command == commands[ASTRO_GET_LOCATION])
1769 auto geo = KStarsData::Instance()->
geo();
1772 {
"name",
geo->name()},
1773 {
"longitude",
geo->lng()->Degrees()},
1774 {
"latitude",
geo->lat()->Degrees()},
1775 {
"elevation",
geo->elevation()},
1780 sendResponse(commands[ASTRO_GET_LOCATION], location);
1783 else if (command == commands[ASTRO_SEARCH_OBJECTS])
1786 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
1795 auto objectType =
static_cast<SkyObject::TYPE>(payload[
"type"].toInt(SkyObject::GALAXY));
1797 auto objectDirection =
static_cast<Direction
>(payload[
"direction"].toInt(All));
1799 auto objectMaxMagnitude = payload[
"maxMagnitude"].toDouble(10);
1801 auto objectMinAlt = payload[
"minAlt"].toDouble(15);
1803 auto objectMinDuration = payload[
"minDuration"].toInt(3600);
1805 auto objectMinFOV = payload[
"minFOV"].toDouble(0);
1807 auto *data = KStarsData::Instance();
1809 auto *
geo = KStarsData::Instance()->
geo();
1812 auto start = KStarsData::Instance()->
lt();
1813 auto end = getNextDawn();
1819 CatalogsDB::CatalogObjectList dsoObjects;
1825 case SkyObject::STAR:
1826 case SkyObject::CATALOG_STAR:
1827 allObjects.
append(data->skyComposite()->objectLists(SkyObject::STAR));
1828 allObjects.
append(data->skyComposite()->objectLists(SkyObject::CATALOG_STAR));
1831 case SkyObject::PLANET:
1832 case SkyObject::MOON:
1833 allObjects.
append(data->skyComposite()->objectLists(SkyObject::PLANET));
1834 allObjects.
append(data->skyComposite()->objectLists(SkyObject::MOON));
1837 case SkyObject::COMET:
1838 allObjects.
append(data->skyComposite()->objectLists(SkyObject::COMET));
1840 case SkyObject::ASTEROID:
1841 allObjects.
append(data->skyComposite()->objectLists(SkyObject::ASTEROID));
1844 case SkyObject::OPEN_CLUSTER:
1845 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::OPEN_CLUSTER, objectMaxMagnitude));
1848 case SkyObject::GLOBULAR_CLUSTER:
1849 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GLOBULAR_CLUSTER, objectMaxMagnitude));
1853 case SkyObject::GASEOUS_NEBULA:
1854 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GASEOUS_NEBULA, objectMaxMagnitude));
1857 case SkyObject::PLANETARY_NEBULA:
1858 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::PLANETARY_NEBULA, objectMaxMagnitude));
1861 case SkyObject::GALAXY:
1862 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GALAXY, objectMaxMagnitude));
1865 case SkyObject::SUPERNOVA:
1867 if (!Options::showSupernovae())
1869 Options::setShowSupernovae(
true);
1870 data->setFullTimeUpdate();
1873 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SUPERNOVA));
1876 case SkyObject::SATELLITE:
1878 if (!Options::showSatellites())
1880 Options::setShowSatellites(
true);
1881 data->setFullTimeUpdate();
1884 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SATELLITE));
1892 std::sort(allObjects.
begin(), allObjects.
end(), [](
const auto & a,
const auto & b)
1894 return a.second->mag() < b.second->mag();
1897 QMutableVectorIterator<QPair<QString, const SkyObject *>> objectIterator(allObjects);
1900 if (objectDirection != All)
1902 QPair<int, int> Quardent1(270, 360), Quardent2(0, 90), Quardent3(90, 180), Quardent4(180, 270);
1903 QPair<int, int> minAZ, maxAZ;
1904 switch (objectDirection)
1928 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1929 while (dsoIterator != dsoObjects.end())
1932 const double az = (*dsoIterator).recomputeHorizontalCoords(start, geo).az().Degrees();
1933 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1934 dsoIterator = dsoObjects.erase(dsoIterator);
1941 while (objectIterator.hasNext())
1943 const auto az = objectIterator.next().second->recomputeHorizontalCoords(start, geo).az().Degrees();
1944 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1945 objectIterator.remove();
1953 objectIterator.toFront();
1954 while (objectIterator.hasNext())
1956 auto magnitude = objectIterator.next().second->mag();
1958 if (magnitude != NaN::f && magnitude > objectMaxMagnitude)
1959 objectIterator.remove();
1966 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1967 while (dsoIterator != dsoObjects.end())
1969 double duration = 0;
1972 dms LST =
geo->GSTtoLST(t.gst());
1973 (*dsoIterator).EquatorialToHorizontal(&LST,
geo->lat());
1974 if ((*dsoIterator).alt().Degrees() >= objectMinAlt)
1978 if (duration < objectMinDuration)
1979 dsoIterator = dsoObjects.erase(dsoIterator);
1986 objectIterator.toFront();
1987 while (objectIterator.hasNext())
1989 auto oneObject = objectIterator.next().second;
1990 double duration = 0;
1994 auto LST =
geo->GSTtoLST(t.gst());
1995 const_cast<SkyObject *
>(oneObject)->EquatorialToHorizontal(&LST,
geo->lat());
1996 if (oneObject->alt().Degrees() >= objectMinAlt)
2000 if (duration < objectMinDuration)
2001 objectIterator.remove();
2006 if (isDSO && objectMinFOV > 0)
2008 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
2009 while (dsoIterator != dsoObjects.end())
2011 if ((*dsoIterator).a() < objectMinFOV)
2012 dsoIterator = dsoObjects.erase(dsoIterator);
2019 for (
auto &oneObject : allObjects)
2020 searchObjects.
append(oneObject.second->name());
2021 for (
auto &oneObject : dsoObjects)
2022 searchObjects.
append(oneObject.name());
2027 sendResponse(commands[ASTRO_SEARCH_OBJECTS], response);
2029 else if(command == commands[ASTRO_GET_OBJECT_INFO])
2031 const auto name = payload[
"object"].toString();
2032 bool exact = payload[
"exact"].toBool(
false);
2039 {
"name", exact ?
name : oneObject->
name()},
2041 {
"magnitude", oneObject->
mag()},
2042 {
"ra0", oneObject->
ra0().Hours()},
2043 {
"de0", oneObject->
dec0().Degrees()},
2044 {
"ra", oneObject->
ra().Hours()},
2045 {
"de", oneObject->
dec().Degrees()},
2048 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info);
2057 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info );
2062 else if (command == commands[ASTRO_GET_OBJECTS_INFO])
2065 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2073 bool exact = payload[
"exact"].toBool(
false);
2074 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2077 for (
auto &oneName : objectNames)
2085 {
"name", exact ?
name : oneObject->
name()},
2087 {
"magnitude", oneObject->
mag()},
2088 {
"ra0", oneObject->
ra0().Hours()},
2089 {
"de0", oneObject->
dec0().Degrees()},
2090 {
"ra", oneObject->
ra().Hours()},
2091 {
"de", oneObject->
dec().Degrees()},
2098 info[
"a"] = dsoObject->
a();
2099 info[
"b"] = dsoObject->
b();
2100 info[
"pa"] = dsoObject->
pa();
2103 objectsArray.
append(info);
2107 sendResponse(commands[ASTRO_GET_OBJECTS_INFO], objectsArray);
2110 else if (command == commands[ASTRO_GET_OBJECTS_OBSERVABILITY])
2113 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2121 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2124 bool exact = payload[
"exact"].toBool(
false);
2126 auto *data = KStarsData::Instance();
2128 auto *
geo = KStarsData::Instance()->
geo();
2130 auto ut = data->ut();
2132 for (
auto &oneName : objectNames)
2135 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2139 dms ha(data->lst()->Degrees() - oneObject->
ra().Degrees());
2142 {
"name", exact ?
name : oneObject->
name()},
2143 {
"az", oneObject->
az().Degrees()},
2144 {
"alt", oneObject->
alt().Degrees()},
2148 objectsArray.
append(info);
2152 sendResponse(commands[ASTRO_GET_OBJECTS_OBSERVABILITY], objectsArray);
2154 else if (command == commands[ASTRO_GET_OBJECTS_RISESET])
2157 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2165 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2168 bool exact = payload[
"exact"].toBool(
false);
2170 auto *data = KStarsData::Instance();
2172 auto *
geo = KStarsData::Instance()->
geo();
2178 if (data->lt().time().hour() > 12)
2181 for (
auto &oneName : objectNames)
2184 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2194 if (transitTime < riseTime)
2201 if (setTime < riseTime)
2204 info[
"name"] = exact ?
name : oneObject->
name();
2212 if (oneObject->
alt().Degrees() > 0.0)
2214 info[
"rise"] =
"Circumpolar";
2215 info[
"set"] =
"Circumpolar";
2219 info[
"rise"] =
"Never rises";
2220 info[
"set"] =
"Never rises";
2227 for (
double h = -12.0; h <= 12.0; h += 0.5)
2229 double hour = h + (24.0 * DayOffset);
2233 altitudes.
append(oneObject->
alt().Degrees());
2236 info[
"altitudes"] = altitudes;
2238 objectsArray.
append(info);
2242 sendResponse(commands[ASTRO_GET_OBJECTS_RISESET], objectsArray);
2251 if (command == commands[FILE_DEFAULT_PATH])
2253 sendResponse(commands[FILE_DEFAULT_PATH],
2256 else if (command == commands[FILE_DIRECTORY_OPERATION])
2258 auto path = payload[
"path"].toString();
2259 auto operation = payload[
"operation"].toString();
2261 if (operation ==
"create")
2266 {
"operation", operation}
2269 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2271 else if (operation ==
"remove")
2276 {
"operation", operation}
2279 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2281 else if (operation ==
"list")
2283 auto namedFilters = payload[
"namedFilters"].toString(
"*").split(
",");
2288 for (
auto &oneEntry : list)
2292 {
"name", oneEntry.fileName()},
2293 {
"path", oneEntry.absolutePath()},
2294 {
"size", oneEntry.size()},
2295 {
"isFile", oneEntry.isFile()},
2296 {
"creation", oneEntry.birthTime().toSecsSinceEpoch()},
2297 {
"modified", oneEntry.lastModified().toSecsSinceEpoch()}
2300 entries.push_back(info);
2305 {
"result", !entries.empty()},
2306 {
"operation", operation},
2307 {
"payload", entries}
2310 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2312 else if (operation ==
"exists")
2317 {
"operation", operation}
2320 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2335 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
2339 if (nextDawn < localTime)
2348void Message::requestDSLRInfo(
const QString &cameraName)
2350 sendResponse(commands[DSLR_GET_INFO], cameraName);
2356void Message::requestPortSelection(
bool show)
2358 sendResponse(commands[GET_PROFILE_PORT_SELECTION], show);
2364void Message::sendDialog(
const QJsonObject &message)
2366 sendResponse(commands[DIALOG_GET_INFO], message);
2374 for (
auto &nodeManager : m_NodeManagers)
2376 nodeManager->message()->sendResponse(command, payload);
2385 for (
auto &nodeManager : m_NodeManagers)
2387 nodeManager->message()->sendResponse(command, payload);
2394void Message::sendResponse(
const QString &command,
const QString &payload)
2396 for (
auto &nodeManager : m_NodeManagers)
2398 nodeManager->message()->sendResponse(command, payload);
2405void Message::sendResponse(
const QString &command,
bool payload)
2407 for (
auto &nodeManager : m_NodeManagers)
2409 nodeManager->message()->sendResponse(command, payload);
2416void Message::autofocusAborted()
2420 {
"status",
"Aborted"}
2422 sendResponse(commands[NEW_FOCUS_STATE], cStatus);
2428void Message::updateMountStatus(
const QJsonObject &status,
bool throttle)
2433 if (m_ThrottleTS.msecsTo(now) >= THROTTLE_INTERVAL)
2436 sendResponse(commands[NEW_MOUNT_STATE], status);
2440 sendResponse(commands[NEW_MOUNT_STATE], status);
2446void Message::updateCaptureStatus(
const QJsonObject &status)
2448 sendResponse(commands[NEW_CAPTURE_STATE], status);
2454void Message::updateFocusStatus(
const QJsonObject &status)
2456 sendResponse(commands[NEW_FOCUS_STATE], status);
2462void Message::updateGuideStatus(
const QJsonObject &status)
2464 sendResponse(commands[NEW_GUIDE_STATE], status);
2470void Message::updateDomeStatus(
const QJsonObject &status)
2472 sendResponse(commands[NEW_DOME_STATE], status);
2478void Message::updateCapStatus(
const QJsonObject &status)
2480 sendResponse(commands[NEW_CAP_STATE], status);
2486void Message::updateAlignStatus(
const QJsonObject &status)
2488 sendResponse(commands[NEW_ALIGN_STATE], status);
2494void Message::sendConnection()
2498 {
"connected",
true},
2499 {
"online", m_Manager->getEkosStartingStatus() == Ekos::Success}
2502 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
2508void Message::sendStates()
2511 if (m_Manager->captureModule())
2513 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2514 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2515 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2518 if (m_Manager->mountModule())
2522 {
"status", m_Manager->mountModule()->statusString(
false)},
2523 {
"target", m_Manager->capturePreview->mountTarget->text()},
2524 {
"slewRate", m_Manager->mountModule()->slewRate()},
2525 {
"pierSide", m_Manager->mountModule()->pierSide()}
2528 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2531 if (m_Manager->focusModule())
2533 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2534 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2537 if (m_Manager->guideModule())
2539 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2540 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2543 if (m_Manager->alignModule())
2548 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2550 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2553 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2560 doc.
setHtml(paa->getPAHMessage());
2563 {
"stage", paa->getPAHStageString(
false)},
2567 sendResponse(commands[NEW_POLAR_STATE], polarState);
2575void Message::sendEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
2577 if (Options::ekosLiveNotifications() ==
false)
2583 {
"severity",
event},
2584 {
"message", message},
2588 sendResponse(commands[NEW_NOTIFICATION], newEvent);
2594void Message::sendManualRotatorStatus(
double currentPA,
double targetPA,
double threshold)
2596 QJsonObject request = {{
"currentPA", currentPA}, {
"targetPA", targetPA}, {
"threshold", threshold}};
2597 sendResponse(commands[ALIGN_MANUAL_ROTATOR_STATUS], request);
2603void Message::setBoundingRect(
QRect rect,
QSize view,
double currentZoom)
2605 m_BoundingRect = rect;
2607 m_CurrentZoom = currentZoom;
2613void Message::processDialogResponse(
const QJsonObject &payload)
2621void Message::processNewProperty(INDI::Property prop)
2626 if (m_Manager->settleStatus() != Ekos::CommunicationStatus::Success)
2630 ISD::propertyToJson(prop, propObject,
false);
2631 sendResponse(commands[DEVICE_PROPERTY_ADD], propObject);
2637void Message::processDeleteProperty(INDI::Property prop)
2641 {
"device", prop.getDeviceName()},
2642 {
"name", prop.getName()}
2645 sendResponse(commands[DEVICE_PROPERTY_REMOVE], payload);
2653 if (Options::ekosLiveNotifications() ==
false)
2659 {
"device", device->getDeviceName()},
2660 {
"message", message}
2663 sendResponse(commands[DEVICE_MESSAGE], payload);
2669void Message::processUpdateProperty(INDI::Property prop)
2671 if (m_PropertySubscriptions.contains(prop.getDeviceName()))
2673 QSet<QString> subProps = m_PropertySubscriptions[prop.getDeviceName()];
2674 if (subProps.
contains(prop.getName()))
2676 m_PendingProperties.remove(prop);
2677 m_PendingProperties.insert(prop);
2685void Message::setPendingPropertiesEnabled(
bool enabled)
2688 m_PendingPropertiesTimer.start();
2691 m_PendingProperties.clear();
2693 if (m_PendingPropertiesTimer.isActive())
2695 m_PendingPropertiesTimer.stop();
2696 std::this_thread::sleep_for(std::chrono::milliseconds(500));
2704void Message::sendPendingProperties()
2706 for (
auto &prop : m_PendingProperties)
2708 if (prop->isValid())
2711 ISD::propertyToJson(*prop, propObject);
2712 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
2716 m_PendingProperties.clear();
2722void Message::sendModuleState(
const QString &name)
2724 if (name ==
"Capture")
2726 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2727 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2728 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2730 else if (name ==
"Mount")
2734 {
"status", m_Manager->mountStatus->getStatusText()},
2735 {
"target", m_Manager->capturePreview->mountTarget->text()},
2736 {
"slewRate", m_Manager->mountModule()->slewRate()},
2737 {
"pierSide", m_Manager->mountModule()->pierSide()}
2740 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2742 else if (name ==
"Focus")
2744 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2745 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2747 else if (name ==
"Guide")
2749 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2750 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2752 else if (name ==
"Align")
2757 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2759 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2762 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2769 doc.
setHtml(paa->getPAHMessage());
2772 {
"stage", paa->getPAHStageString(
false)},
2776 sendResponse(commands[NEW_POLAR_STATE], polarState);
2788 if (name ==
"Manager")
2802 for (
auto &tab : viewer->tabs())
2804 if (tab->getView()->objectName() == name)
2805 return tab->getView().get();
2818#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2819bool Message::parseArgument(
QVariant::Type type,
const QVariant &arg, QMetaMethodArgument &genericArg, SimpleTypes &types)
2828 case QVariant::Type::Int:
2829 types.number_integer = arg.
toInt();
2830 genericArg = Q_ARG(
int, types.number_integer);
2832 case QVariant::Type::UInt:
2833 types.number_unsigned_integer = arg.
toUInt();
2834 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2836 case QVariant::Type::LongLong:
2838 genericArg = Q_ARG(
int, types.number_integer);
2840 case QVariant::Type::ULongLong:
2841 types.number_unsigned_integer = arg.
toULongLong();
2842 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2844 case QVariant::Type::Double:
2845 types.number_double = arg.
toDouble();
2846 genericArg = Q_ARG(
double, types.number_double);
2848 case QVariant::Type::Bool:
2849 types.boolean = arg.
toBool();
2850 genericArg = Q_ARG(
bool, types.boolean);
2852 case QVariant::Type::String:
2854 genericArg = Q_ARG(
QString, types.text);
2856 case QVariant::Type::Url:
2857 types.url = arg.
toUrl();
2858 genericArg = Q_ARG(
QUrl, types.
url);
2872#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2880 auto name = payload[
"name"].toString().toLatin1();
2886 for (
auto oneArg : args)
2888 auto argObject = oneArg.toObject();
2889#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2890 QMetaMethodArgument genericArgument;
2894 SimpleTypes genericType;
2895 argsList.
append(genericArgument);
2896 typesList.
append(genericType);
2897 if (parseArgument(
static_cast<QVariant::Type>(argObject[
"type"].toInt()), argObject[
"value"].toVariant(), argsList.
back(),
2898 typesList.
last()) ==
false)
2905 switch (argsList.
size())
a dms subclass that caches its sine and cosine values every time the angle is changed.
A simple container object to hold the minimum information for a Deep Sky Object to be drawn on the sk...
double pa() const override
Align class handles plate-solving and polar alignment measurement and correction using astrometry....
bool loadAndSlew(const QByteArray &image, const QString &extension)
DBUS interface function.
void stop()
stop Abort all dark job captures.
Performs calibration and autoguiding using an ST4 port or directly via the INDI driver.
Q_SCRIPTABLE bool capture()
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void clearCalibration()
DBUS interface function.
Q_SCRIPTABLE bool abort()
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void loop()
DBUS interface function.
Q_SCRIPTABLE bool guide()
DBUS interface function.
Supports controlling INDI telescope devices including setting/retrieving mount properties,...
void setOpticalTrainID(uint32_t id)
setOpticalTrainID This must be called before calling any settings functions below.
The PolarAlignmentAssistant class.
The Ekos scheduler is a simple scheduler class to orchestrate automated multi object observation jobs...
Q_INVOKABLE void addJob(SchedulerJob *job=nullptr)
addJob Add a new job from form values
bool importMosaic(const QJsonObject &payload)
importMosaic Import mosaic into planner and generate jobs for the scheduler.
bool loadFile(const QUrl &path)
loadFile Load scheduler jobs from disk
bool saveFile(const QUrl &path)
saveFile Save scheduler jobs to disk
void removeOneJob(int index)
Remove a job by selecting a table row.
Camera class controls an INDI Camera device.
Q_INVOKABLE QAction * action(const QString &name) const
A class that implements methods to find sun rise, sun set, twilight begin / end times,...
bool selectResponse(const QString &button)
selectResponse Programatically select one the buttons in the dialog.
bool GetAllScopes(QList< OAL::Scope * > &m_scopeList)
updates the scope list with all scopes from database List is cleared and then filled with content.
bool AddDSLRLens(const QString &model, const QString &vendor, const double focalLength, const double focalRatio)
Appends the DSLR lens with given details in the database.
bool AddScope(const QString &model, const QString &vendor, const QString &type, const double &aperture, const double &focalLength)
Appends the scope with given details in the database.
bool DeleteEquipment(const QString &type, const QString &id)
Erase the equipment with given type and unique id Valid equipment types: "telescope",...
bool GetAllDSLRLenses(QList< OAL::DSLRLens * > &dslrlens_list)
updates the dslr list with all DSLR lenses from database List is cleared and then filled with content...
const KStarsDateTime & lt() const
void changeDateTime(const KStarsDateTime &newDate)
Change the current simulation date/time to the KStarsDateTime argument.
Q_INVOKABLE SimClock * clock()
SkyMapComposite * skyComposite()
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
KStarsDateTime addDays(int nd) const
Modify the Date/Time by adding a number of days.
KStarsDateTime addSecs(double s) const
static KStarsDateTime currentDateTimeUtc()
static KStars * Instance()
virtual KActionCollection * actionCollection() const
void setManualMode(bool on=true)
Sets Manual Mode on/off according to the bool argument.
Q_SCRIPTABLE Q_NOREPLY void start()
DBUS function to start the SimClock.
Q_SCRIPTABLE Q_NOREPLY void setUTC(const KStarsDateTime &newtime)
DBUS function to set the time of the SimClock.
Q_SCRIPTABLE Q_NOREPLY void stop()
DBUS function to stop the SimClock.
SkyObject * findByName(const QString &name, bool exact=true) override
Search the children of this SkyMapComposite for a SkyObject whose name matches the argument.
void forceUpdate(bool now=false)
Recalculates the positions of objects in the sky, and then repaints the sky map.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
virtual QString name(void) const
virtual QString longname(void) const
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
TYPE
The type classification of the SkyObject.
The sky coordinates of a point in the sky.
void apparentCoord(long double jd0, long double jdf)
Computes the apparent coordinates for this SkyPoint for any epoch, accounting for the effects of prec...
const CachingDms & dec() const
const CachingDms & ra0() const
const CachingDms & ra() const
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
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.
Q_SCRIPTABLE bool captureAndSolve(bool initialCall=true)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void abort()
DBUS interface function.
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
Generic record interfaces and implementations.
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
GeoCoordinates geo(const QVariant &location)
QVariant location(const QVariant &res)
QString path(const QString &relativePath)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString name(StandardAction id)
const QList< QKeySequence > & end()
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
void setCurrentIndex(int index)
QDateTime currentDateTime()
QFileInfoList entryInfoList(Filters filters, SortFlags sort) const const
bool exists() const const
bool mkpath(const QString &dirPath) const const
virtual void close() override
qint64 write(const QByteArray &data)
void append(const QJsonValue &value)
QJsonArray fromStringList(const QStringList &list)
bool isEmpty() const const
QVariantList toVariantList() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool contains(QLatin1StringView key) const const
QJsonObject fromVariantMap(const QVariantMap &map)
iterator insert(QLatin1StringView key, const QJsonValue &value)
QVariantMap toVariantMap() const const
qreal angle() const const
qreal length() const const
void append(QList< T > &&value)
qsizetype size() const const
T findChild(const QString &name, Qt::FindChildOptions options) const const
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
bool remove(const T &value)
bool isNull() const const
QString arg(Args &&... args) const const
QString asprintf(const char *cformat,...)
QString fromLatin1(QByteArrayView str)
QString fromStdString(const std::string &str)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QByteArray toLatin1() const const
QByteArray toUtf8() const const
qsizetype removeDuplicates()
void sort(Qt::CaseSensitivity cs)
QTextStream & center(QTextStream &stream)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
virtual QString fileName() const const override
void setAutoRemove(bool b)
void setHtml(const QString &html)
QString toPlainText() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isValid(int h, int m, int s, int ms)
QUrl fromLocalFile(const QString &localFile)
QString url(FormattingOptions options) const const
QString toString(StringFormat mode) const const
bool toBool() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
qlonglong toLongLong(bool *ok) const const
QString toString() const const
uint toUInt(bool *ok) const const
qulonglong toULongLong(bool *ok) const const