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"
26#include "kstarsdata.h"
27#include "ekos_debug.h"
29#include "skymapcomposite.h"
30#include "catalogobject.h"
31#include "fitsviewer/fitsviewer.h"
32#include "fitsviewer/fitstab.h"
33#include "ekos/auxiliary/darklibrary.h"
38#include <KActionCollection>
39#include <basedevice.h>
46 m_Manager(manager), m_NodeManagers(nodeManagers), m_DSOManager(CatalogsDB::dso_db_path())
48 for (
auto &nodeManager : m_NodeManagers)
50 connect(nodeManager->message(), &Node::connected,
this, &Message::onConnected);
51 connect(nodeManager->message(), &Node::disconnected,
this, &Message::onDisconnected);
52 connect(nodeManager->message(), &Node::onTextReceived,
this, &Message::onTextReceived);
55 connect(manager, &Ekos::Manager::newModule,
this, &Message::sendModuleState);
59 m_PendingPropertiesTimer.setInterval(500);
62 m_DebouncedSend.setInterval(500);
69void Message::onConnected()
71 auto node = qobject_cast<Node*>(sender());
75 qCInfo(KSTARS_EKOS) <<
"Connected to Message Websocket server at" << node->url().toDisplayString();
77 m_PendingPropertiesTimer.start();
86void Message::onDisconnected()
88 auto node = qobject_cast<Node*>(sender());
92 qCInfo(KSTARS_EKOS) <<
"Disconnected from Message Websocket server at" << node->url().toDisplayString();
94 if (isConnected() ==
false)
96 m_PendingPropertiesTimer.stop();
104void Message::onTextReceived(
const QString &message)
106 auto node = qobject_cast<Node*>(sender());
107 if (!node || message.
isEmpty())
110 qCInfo(KSTARS_EKOS) <<
"Websocket Message" << message;
115 qCWarning(KSTARS_EKOS) <<
"Ekos Live Parsing Error" <<
error.errorString();
120 const QString command = msgObj[
"type"].toString();
121 const QJsonObject payload = msgObj[
"payload"].toObject();
123 if (command == commands[GET_CONNECTION])
127 else if (command == commands[LOGOUT] || command == commands[SESSION_EXPIRED])
129 emit expired(node->url());
132 else if (command == commands[SET_CLIENT_STATE])
135 if (payload[
"state"].toBool(
false))
137 qCInfo(KSTARS_EKOS) <<
"EkosLive client is connected.";
140 if (KStarsData::Instance()->clock()->isActive() ==
false)
142 qCInfo(KSTARS_EKOS) <<
"Resuming and syncing clock.";
153 qCInfo(KSTARS_EKOS) <<
"EkosLive client is disconnected.";
155 if (
KStars::Instance()->isStartedWithClockRunning() ==
false && m_Manager->ekosStatus() == Ekos::CommunicationStatus::Idle)
157 qCInfo(KSTARS_EKOS) <<
"Stopping the clock.";
162 else if (command == commands[GET_DRIVERS])
164 else if (command == commands[GET_PROFILES])
166 else if (command == commands[GET_SCOPES])
168 else if (command == commands[GET_DSLR_LENSES])
170 else if(command == commands[INVOKE_METHOD])
172 auto object = findObject(payload[
"object"].
toString());
174 invokeMethod(
object, payload);
176 else if(command == commands[SET_PROPERTY])
178 auto object = findObject(payload[
"object"].
toString());
180 object->setProperty(payload[
"name"].
toString().toLatin1().constData(), payload[
"value"].toVariant());
182 else if(command == commands[GET_PROPERTY])
184 auto map = QVariantMap();
185 map[
"result"] =
false;
186 auto object = findObject(payload[
"object"].
toString());
189 auto value =
object->property(payload[
"name"].
toString().toLatin1().constData());
192 map[
"result"] =
true;
193 map[
"value"] = value;
198 else if (command == commands[TRAIN_GET_ALL])
200 else if (command == commands[TRAIN_SETTINGS_GET])
202 auto id = payload[
"id"].toInt(-1);
206 auto settings = Ekos::OpticalTrainSettings::Instance()->getSettings();
207 if (!settings.isEmpty())
212 processScopeCommands(command, payload);
214 processProfileCommands(command, payload);
216 processAstronomyCommands(command, payload);
217 else if (command == commands[DIALOG_GET_RESPONSE])
218 processDialogResponse(payload);
220 processOptionsCommands(command, payload);
222 processSchedulerCommands(command, payload);
224 processDSLRCommands(command, payload);
226 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
229 if (command == commands[GET_STATES])
231 else if (command == commands[GET_STELLARSOLVER_PROFILES])
232 sendStellarSolverProfiles();
233 else if (command == commands[GET_DEVICES])
236 processCaptureCommands(command, payload);
238 processMountCommands(command, payload);
240 processFocusCommands(command, payload);
242 processGuideCommands(command, payload);
244 processAlignCommands(command, payload);
246 processPolarCommands(command, payload);
248 processTrainCommands(command, payload);
250 processFilterManagerCommands(command, payload);
252 processDarkLibraryCommands(command, payload);
254 processDeviceCommands(command, payload);
261bool Message::isConnected()
const
263 return std::any_of(m_NodeManagers.begin(), m_NodeManagers.end(), [](
auto & nodeManager)
265 return nodeManager->message()->isConnected();
272void Message::sendStellarSolverProfiles()
274 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
279 if (m_Manager->focusModule())
284 if (m_Manager->alignModule())
288 sendResponse(commands[GET_STELLARSOLVER_PROFILES], profiles);
294void Message::sendDrivers()
296 sendResponse(commands[GET_DRIVERS], DriverManager::Instance()->getDriverList());
302void Message::sendDevices()
304 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
309 for(
auto &gd : INDIListener::devices())
313 {
"name", gd->getDeviceName()},
314 {
"connected", gd->isConnected()},
315 {
"version", gd->getDriverVersion()},
316 {
"interface",
static_cast<int>(gd->getDriverInterface())},
319 deviceList.
append(oneDevice);
322 sendResponse(commands[GET_DEVICES], deviceList);
328void Message::sendTrains()
332 for(
auto &train : Ekos::OpticalTrainManager::Instance()->getOpticalTrains())
335 sendResponse(commands[TRAIN_GET_ALL], trains);
341void Message::sendTrainProfiles()
343 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
346 auto profiles = Ekos::ProfileSettings::Instance()->getSettings();
354void Message::requestOpticalTrains(
bool show)
356 sendResponse(commands[TRAIN_CONFIGURATION_REQUESTED], show);
362void Message::sendScopes()
369 for (
auto &scope : allScopes)
370 scopeList.
append(scope->toJson());
372 sendResponse(commands[GET_SCOPES], scopeList);
378void Message::sendDSLRLenses()
385 for (
auto &dslrLens : allDslrLens)
386 dslrList.
append(dslrLens->toJson());
388 sendResponse(commands[GET_DSLR_LENSES], dslrList);
394void Message::sendTemperature(
double value)
402 {
"name", oneCCD->getDeviceName()},
403 {
"temperature", value}
406 sendResponse(commands[NEW_CAMERA_STATE], temperature);
413void Message::processCaptureCommands(
const QString &command,
const QJsonObject &payload)
415 auto capture = m_Manager->captureModule();
417 if (capture ==
nullptr)
419 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as capture module is not available";
423 if (command == commands[CAPTURE_PREVIEW])
425 capture->mainCamera()->capturePreview();
427 else if (command == commands[CAPTURE_TOGGLE_VIDEO])
429 capture->setVideoLimits(payload[
"maxBufferSize"].toInt(512), payload[
"maxPreviewFPS"].toInt(10));
430 capture->toggleVideo(payload[
"enabled"].toBool());
432 else if (command == commands[CAPTURE_START])
434 else if (command == commands[CAPTURE_STOP])
436 else if (command == commands[CAPTURE_LOOP])
438 capture->mainCamera()->startFraming();
440 else if (command == commands[CAPTURE_GET_SEQUENCES])
442 sendCaptureSequence(capture->getSequence());
444 else if (command == commands[CAPTURE_ADD_SEQUENCE])
447 capture->mainCamera()->createJob();
449 else if (command == commands[CAPTURE_REMOVE_SEQUENCE])
451 if (capture->mainCamera()->removeJob(payload[
"index"].toInt()) ==
false)
452 sendCaptureSequence(capture->getSequence());
454 else if (command == commands[CAPTURE_CLEAR_SEQUENCES])
456 capture->clearSequenceQueue();
458 else if (command == commands[CAPTURE_SAVE_SEQUENCE_FILE])
460 if (capture->saveSequenceQueue(payload[
"filepath"].toString()))
463 else if (command == commands[CAPTURE_LOAD_SEQUENCE_FILE])
478 path = payload[
"filepath"].toString();
482 auto result = capture->loadSequenceQueue(path);
488 sendResponse(commands[CAPTURE_LOAD_SEQUENCE_FILE], response);
491 else if (command == commands[CAPTURE_GET_ALL_SETTINGS])
493 sendCaptureSettings(capture->mainCamera()->getAllSettings());
495 else if (command == commands[CAPTURE_SET_ALL_SETTINGS])
498 capture->mainCamera()->setAllSettings(settings);
499 KSUtils::setGlobalSettings(settings);
501 else if (command == commands[CAPTURE_GENERATE_DARK_FLATS])
503 capture->mainCamera()->generateDarkFlats();
510void Message::sendCaptureSequence(
const QJsonArray &sequenceArray)
512 sendResponse(commands[CAPTURE_GET_SEQUENCES], sequenceArray);
515void Message::sendPreviewLabel(
const QString &preview)
521 sendResponse(commands[CAPTURE_GET_PREVIEW_LABEL], payload);
527void Message::sendCaptureSettings(
const QVariantMap &settings)
529 m_DebouncedSend.start();
530 m_DebouncedMap[commands[CAPTURE_GET_ALL_SETTINGS]] = settings;
536void Message::sendAlignSettings(
const QVariantMap &settings)
538 m_DebouncedSend.start();
539 m_DebouncedMap[commands[ALIGN_GET_ALL_SETTINGS]] = settings;
545void Message::sendGuideSettings(
const QVariantMap &settings)
547 m_DebouncedSend.start();
548 m_DebouncedMap[commands[GUIDE_GET_ALL_SETTINGS]] = settings;
555void Message::sendFocusSettings(
const QVariantMap &settings)
557 m_DebouncedSend.start();
558 m_DebouncedMap[commands[FOCUS_GET_ALL_SETTINGS]] = settings;
564void Message::sendMountSettings(
const QVariantMap &settings)
566 m_DebouncedSend.start();
567 m_DebouncedMap[commands[MOUNT_GET_ALL_SETTINGS]] = settings;
573void Message::sendDarkLibrarySettings(
const QVariantMap &settings)
575 m_DebouncedSend.start();
576 m_DebouncedMap[commands[DARK_LIBRARY_GET_ALL_SETTINGS]] = settings;
583void Message::sendSchedulerSettings(
const QVariantMap &settings)
585 m_DebouncedSend.start();
586 m_DebouncedMap[commands[SCHEDULER_GET_ALL_SETTINGS]] = settings;
592void Message::dispatchDebounceQueue()
600 m_DebouncedMap.clear();
603 Options::self()->save();
613 if (guide ==
nullptr)
615 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as guide module is not available";
619 if (command == commands[GUIDE_START])
623 else if (command == commands[GUIDE_CAPTURE])
625 else if (command == commands[GUIDE_LOOP])
627 else if (command == commands[GUIDE_STOP])
629 else if (command == commands[GUIDE_CLEAR])
631 else if (command == commands[GUIDE_SET_ALL_SETTINGS])
634 guide->setAllSettings(settings);
635 KSUtils::setGlobalSettings(settings);
637 else if (command == commands[GUIDE_GET_ALL_SETTINGS])
638 sendGuideSettings(guide->getAllSettings());
639 else if(command == commands[GUIDE_SET_CALIBRATION_SETTINGS])
642 Options::setCalibrationPulseDuration(payload[
"pulse"].toInt());
643 Options::setGuideCalibrationBacklash(payload[
"max_move"].toInt());
644 Options::setTwoAxisEnabled(payload[
"two_axis"].toBool());
645 Options::setGuideAutoSquareSizeEnabled(payload[
"square_size"].toBool());
646 Options::setGuideCalibrationBacklash(payload[
"calibrationBacklash"].toBool());
647 Options::setResetGuideCalibration(payload[
"resetCalibration"].toBool());
648 Options::setReuseGuideCalibration(payload[
"reuseCalibration"].toBool());
649 Options::setReverseDecOnPierSideChange(payload[
"reverseCalibration"].toBool());
650 sendGuideSettings(m_Manager->guideModule()->getAllSettings());
660 if (m_Manager->focusModule())
661 focus = m_Manager->focusModule()->mainFocuser();
665 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as focus module is not available";
669 if (command == commands[FOCUS_START])
671 else if (command == commands[FOCUS_CAPTURE])
676 else if (command == commands[FOCUS_STOP])
678 else if (command == commands[FOCUS_RESET])
680 else if (command == commands[FOCUS_IN])
681 focus->focusIn(payload[
"steps"].toInt());
682 else if (command == commands[FOCUS_OUT])
683 focus->focusOut(payload[
"steps"].toInt());
684 else if (command == commands[FOCUS_LOOP])
685 focus->startFraming();
686 else if (command == commands[FOCUS_SET_ALL_SETTINGS])
689 focus->setAllSettings(settings);
690 KSUtils::setGlobalSettings(settings);
693 else if (command == commands[FOCUS_GET_ALL_SETTINGS])
694 sendFocusSettings(focus->getAllSettings());
695 else if (command == commands[FOCUS_SET_CROSSHAIR])
697 double x = payload[
"x"].toDouble();
698 double y = payload[
"y"].toDouble();
699 focus->selectFocusStarFraction(x, y);
710 if (mount ==
nullptr)
712 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as mount module is not available";
716 if (command == commands[MOUNT_ABORT])
718 else if (command == commands[MOUNT_PARK])
720 else if (command == commands[MOUNT_UNPARK])
722 else if (command == commands[MOUNT_SET_TRACKING])
723 mount->setTrackEnabled(payload[
"enabled"].toBool());
724 else if (command == commands[MOUNT_SYNC_RADE])
726 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
729 mount->sync(ra.Hours(), de.Degrees());
731 else if (command == commands[MOUNT_SYNC_TARGET])
735 else if (command == commands[MOUNT_GOTO_RADE])
737 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
740 mount->slew(ra.Hours(), de.Degrees());
742 else if (command == commands[MOUNT_GOTO_TARGET])
746 else if (command == commands[MOUNT_SET_SLEW_RATE])
748 int rate = payload[
"rate"].toInt(-1);
750 mount->setSlewRate(rate);
752 else if (command == commands[MOUNT_SET_ALL_SETTINGS])
755 mount->setAllSettings(settings);
756 KSUtils::setGlobalSettings(settings);
758 else if (command == commands[MOUNT_GET_ALL_SETTINGS])
759 sendMountSettings(
mount->getAllSettings());
760 else if (command == commands[MOUNT_SET_MOTION])
762 QString direction = payload[
"direction"].toString();
763 ISD::Mount::MotionCommand action = payload[
"action"].toBool(
false) ?
764 ISD::Mount::MOTION_START : ISD::Mount::MOTION_STOP;
766 if (direction ==
"N")
767 mount->motionCommand(action, ISD::Mount::MOTION_NORTH, -1);
768 else if (direction ==
"S")
769 mount->motionCommand(action, ISD::Mount::MOTION_SOUTH, -1);
770 else if (direction ==
"E")
771 mount->motionCommand(action, -1, ISD::Mount::MOTION_EAST);
772 else if (direction ==
"W")
773 mount->motionCommand(action, -1, ISD::Mount::MOTION_WEST);
775 else if (command == commands[MOUNT_GOTO_PIXEL])
777 const auto name = payload[
"camera"].toString();
778 const auto xFactor = payload[
"x"].toDouble();
779 const auto yFactor = payload[
"y"].toDouble();
781 for(
auto &oneDevice : INDIListener::devices())
783 auto camera = oneDevice->getCamera();
784 if (!camera || camera->getDeviceName() != name)
787 auto primaryChip = camera->getChip(ISD::CameraChip::PRIMARY_CCD);
792 auto imageData = primaryChip->getImageData();
793 if (!imageData || imageData->hasWCS() ==
false)
796 auto x = xFactor * imageData->width();
797 auto y = yFactor * imageData->height();
801 if (imageData->pixelToWCS(point, coord))
805 mount->gotoTarget(coord);
810 else if (command == commands[MOUNT_TOGGLE_AUTOPARK])
811 mount->setAutoParkEnabled(payload[
"toggled"].toBool());
821 if (align ==
nullptr)
823 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as align module is not available";
827 if (command == commands[ALIGN_SOLVE])
831 else if (command == commands[ALIGN_SET_ALL_SETTINGS])
834 align->setAllSettings(settings);
835 KSUtils::setGlobalSettings(settings);
837 else if (command == commands[ALIGN_GET_ALL_SETTINGS])
838 sendAlignSettings(align->getAllSettings());
839 else if(command == commands[ALIGN_SET_ASTROMETRY_SETTINGS])
841 Options::setAstrometryRotatorThreshold(payload[
"threshold"].toInt());
842 Options::setAstrometryUseRotator(payload[
"rotator_control"].toBool());
843 Options::setAstrometryUseImageScale(payload[
"scale"].toBool());
844 Options::setAstrometryUsePosition(payload[
"position"].toBool());
846 else if (command == commands[ALIGN_STOP])
848 else if (command == commands[ALIGN_LOAD_AND_SLEW])
867 else if (command == commands[ALIGN_MANUAL_ROTATOR_TOGGLE])
869 align->toggleManualRotator(payload[
"toggled"].toBool());
878 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
886 sendResponse(commands[NEW_ALIGN_STATE], alignState);
892void Message::setAlignSolution(
const QVariantMap &solution)
894 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
902 sendResponse(commands[NEW_ALIGN_STATE], alignState);
908void Message::processSchedulerCommands(
const QString &command,
const QJsonObject &payload)
912 if (command == commands[SCHEDULER_GET_JOBS])
916 else if (command == commands[SCHEDULER_ADD_JOBS])
920 else if(command == commands[SCHEDULER_REMOVE_JOBS])
922 int index = payload[
"index"].toInt();
925 else if(command == commands[SCHEDULER_GET_ALL_SETTINGS])
927 sendSchedulerSettings(scheduler->getAllSettings());
929 else if(command == commands[SCHEDULER_SET_ALL_SETTINGS])
932 scheduler->setAllSettings(settings);
933 KSUtils::setGlobalSettings(settings);
935 else if (command == commands[SCHEDULER_SAVE_FILE])
940 else if (command == commands[SCHEDULER_SAVE_SEQUENCE_FILE])
961 sendResponse(commands[SCHEDULER_SAVE_SEQUENCE_FILE], response);
963 else if (command == commands[SCHEDULER_LOAD_FILE])
978 path = payload[
"filepath"].toString();
988 sendResponse(commands[SCHEDULER_LOAD_FILE], response);
991 else if(command == commands[SCHEDULER_START_JOB])
993 scheduler->toggleScheduler();
995 else if(command == commands[SCHEDULER_IMPORT_MOSAIC])
1000 sendEvent(
i18n(
"Mosaic import failed."), KSNotification::Scheduler, KSNotification::Alert);
1007void Message::processPolarCommands(
const QString &command,
const QJsonObject &payload)
1015 if (command == commands[PAH_START])
1017 paa->startPAHProcess();
1019 if (command == commands[PAH_STOP])
1021 paa->stopPAHProcess();
1023 else if (command == commands[PAH_REFRESH])
1025 paa->setPAHRefreshDuration(payload[
"value"].toDouble(1));
1026 paa->startPAHRefreshProcess();
1028 else if (command == commands[PAH_SET_ALGORITHM])
1032 algorithmCombo->
setCurrentIndex(
static_cast<Ekos::PolarAlignmentAssistant::RefreshAlgorithm
>(payload[
"value"].toInt(1)));
1034 else if (command == commands[PAH_RESET_VIEW])
1036 emit resetPolarView();
1038 else if (command == commands[PAH_SET_CROSSHAIR])
1040 double x = payload[
"x"].toDouble();
1041 double y = payload[
"y"].toDouble();
1043 if (m_BoundingRect.isNull() ==
false)
1047 double boundX = x * m_BoundingRect.width();
1048 double boundY = y * m_BoundingRect.height();
1053 x = ((boundX + m_BoundingRect.x()) / (m_CurrentZoom / 100)) / m_ViewSize.width();
1054 y = ((boundY + m_BoundingRect.y()) / (m_CurrentZoom / 100)) / m_ViewSize.height();
1058 paa->setPAHCorrectionOffsetPercentage(x, y);
1060 else if (command == commands[PAH_SELECT_STAR_DONE])
1066 else if (command == commands[PAH_REFRESHING_DONE])
1068 paa->stopPAHProcess();
1070 else if (command == commands[PAH_SLEW_DONE])
1072 paa->setPAHSlewDone();
1074 else if (command == commands[PAH_PAH_SET_ZOOM])
1076 double scale = payload[
"scale"].toDouble();
1077 align->setAlignZoom(scale);
1085void Message::setPAHStage(Ekos::PolarAlignmentAssistant::Stage stage)
1087 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1100 {
"stage", paa->getPAHStageString(
false)}
1105 if (stage == Ekos::PolarAlignmentAssistant::PAH_STAR_SELECT)
1106 align->zoomAlignView();
1108 sendResponse(commands[NEW_POLAR_STATE], polarState);
1114void Message::setPAHMessage(
const QString &message)
1116 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1126 sendResponse(commands[NEW_POLAR_STATE], polarState);
1132void Message::setPolarResults(
QLineF correctionVector,
double polarError,
double azError,
double altError)
1134 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1137 this->correctionVector = correctionVector;
1142 {
"center_x",
center.x()},
1143 {
"center_y",
center.y()},
1144 {
"mag", correctionVector.
length()},
1145 {
"pa", correctionVector.
angle()},
1146 {
"error", polarError},
1147 {
"azError", azError},
1148 {
"altError", altError}
1156 sendResponse(commands[NEW_POLAR_STATE], polarState);
1162void Message::setUpdatedErrors(
double total,
double az,
double alt)
1164 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1169 {
"updatedError", total},
1170 {
"updatedAZError", az},
1171 {
"updatedALTError", alt}
1174 sendResponse(commands[NEW_POLAR_STATE], error);
1180void Message::setPAHEnabled(
bool enabled)
1182 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
1187 {
"enabled", enabled}
1190 sendResponse(commands[NEW_POLAR_STATE], polarState);
1196void Message::processProfileCommands(
const QString &command,
const QJsonObject &payload)
1198 if (command == commands[START_PROFILE])
1200 if (m_Manager->getEkosStartingStatus() != Ekos::Idle)
1203 m_Manager->setProfile(payload[
"name"].
toString());
1208 else if (command == commands[STOP_PROFILE])
1215 m_PropertySubscriptions.clear();
1217 else if (command == commands[ADD_PROFILE])
1219 m_Manager->addNamedProfile(payload);
1222 else if (command == commands[UPDATE_PROFILE])
1224 m_Manager->editNamedProfile(payload);
1227 else if (command == commands[GET_PROFILE])
1229 m_Manager->getNamedProfile(payload[
"name"].
toString());
1231 else if (command == commands[DELETE_PROFILE])
1233 m_Manager->deleteNamedProfile(payload[
"name"].
toString());
1236 else if (command == commands[SET_PROFILE_MAPPING])
1238 m_Manager->setProfileMapping(payload);
1240 else if (command == commands[SET_PROFILE_PORT_SELECTION])
1242 requestPortSelection(
false);
1243 m_Manager->acceptPortSelection();
1250void Message::sendProfiles()
1255 if (!m_Manager->getCurrentProfile(profile))
1258 for (
auto &oneProfile : m_Manager->profiles)
1259 profileArray.
append(oneProfile->toJson());
1263 {
"selectedProfile", profile->name},
1264 {
"profiles", profileArray}
1266 sendResponse(commands[GET_PROFILES], profiles);
1272void Message::sendSchedulerJobs()
1276 {
"jobs", m_Manager->schedulerModule()->moduleState()->getJSONJobs()}
1278 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1284void Message::sendSchedulerJobList(
QJsonArray jobsList)
1290 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1296void Message::sendSchedulerStatus(
const QJsonObject &status)
1298 sendResponse(commands[NEW_SCHEDULER_STATE], status);
1305void Message::setEkosStatingStatus(Ekos::CommunicationStatus status)
1307 if (status == Ekos::Pending)
1312 {
"connected",
true},
1313 {
"online",
status == Ekos::Success}
1315 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
1321void Message::setINDIStatus(Ekos::CommunicationStatus status)
1328 sendResponse(commands[NEW_INDI_STATE], connectionState);
1334void Message::processOptionsCommands(
const QString &command,
const QJsonObject &payload)
1336 if (command == commands[OPTION_SET])
1338 const QJsonArray options = payload[
"options"].toArray();
1339 for (
const auto &oneOption : options)
1340 Options::self()->setProperty(oneOption[
QString(
"name")].
toString().toLatin1(), oneOption[
QString(
"value")].toVariant());
1342 Options::self()->save();
1343 emit optionsUpdated();
1345 else if (command == commands[OPTION_GET])
1349 for (
const auto &oneOption : options)
1351 const auto name = oneOption[
QString(
"name")].toString();
1355 map[
"value"] = value;
1358 sendResponse(commands[OPTION_GET], result);
1365void Message::processScopeCommands(
const QString &command,
const QJsonObject &payload)
1367 if (command == commands[ADD_SCOPE])
1370 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble());
1372 else if (command == commands[UPDATE_SCOPE])
1375 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble(), payload[
"id"].
toString());
1377 else if (command == commands[DELETE_SCOPE])
1390 if (command == commands[DSLR_SET_INFO])
1392 if (m_Manager->captureModule())
1393 m_Manager->captureModule()->mainCamera()->addDSLRInfo(
1395 payload[
"width"].toInt(),
1396 payload[
"height"].toInt(),
1397 payload[
"pixelw"].toDouble(),
1398 payload[
"pixelh"].toDouble());
1401 else if(command == commands[DSLR_ADD_LENS])
1404 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble());
1406 else if (command == commands[DSLR_DELETE_LENS])
1410 else if (command == commands[DSLR_UPDATE_LENS])
1413 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble(), payload[
"id"].
toString());
1422void Message::processTrainCommands(
const QString &command,
const QJsonObject &payload)
1424 if (command == commands[TRAIN_GET_PROFILES])
1425 sendTrainProfiles();
1426 else if (command == commands[TRAIN_SET])
1428 auto module = payload["module"].toString();
1429 auto name = payload[
"name"].toString();
1431 if (module ==
"capture")
1433 if (m_Manager->captureModule())
1434 m_Manager->captureModule()->setOpticalTrain(name);
1436 else if (module ==
"focus")
1438 if (m_Manager->focusModule())
1439 m_Manager->focusModule()->mainFocuser()->setOpticalTrain(name);
1441 else if (module ==
"guide")
1443 if (m_Manager->guideModule())
1444 m_Manager->guideModule()->setOpticalTrain(name);
1446 else if (module ==
"align")
1448 if (m_Manager->alignModule())
1449 m_Manager->alignModule()->setOpticalTrain(name);
1451 else if (module ==
"mount")
1453 if (m_Manager->mountModule())
1454 m_Manager->mountModule()->setOpticalTrain(name);
1456 else if (module ==
"darklibrary")
1458 Ekos::DarkLibrary::Instance()->setOpticalTrain(name);
1461 else if (command == commands[TRAIN_ADD])
1463 Ekos::OpticalTrainManager::Instance()->addOpticalTrain(payload);
1465 else if (command == commands[TRAIN_UPDATE])
1467 Ekos::OpticalTrainManager::Instance()->setOpticalTrain(payload);
1469 else if (command == commands[TRAIN_DELETE])
1471 Ekos::OpticalTrainManager::Instance()->removeOpticalTrain(payload[
"name"].
toString());
1473 else if (command == commands[TRAIN_RESET])
1475 Ekos::OpticalTrainManager::Instance()->reset();
1477 else if (command == commands[TRAIN_ACCEPT])
1479 requestOpticalTrains(
false);
1480 Ekos::OpticalTrainManager::Instance()->
accept();
1488void Message::processFilterManagerCommands(
const QString &command,
const QJsonObject &payload)
1491 if (m_Manager->captureModule())
1492 manager = m_Manager->captureModule()->mainCamera()->filterManager();
1497 if (command == commands[FM_GET_DATA])
1500 sendResponse(commands[FM_GET_DATA], data);
1502 else if (command == commands[FM_SET_DATA])
1504 manager->setFilterData(payload);
1511void Message::processDarkLibraryCommands(
const QString &command,
const QJsonObject &payload)
1513 if (command == commands[DARK_LIBRARY_START])
1514 Ekos::DarkLibrary::Instance()->start();
1515 else if(command == commands[DARK_LIBRARY_SET_ALL_SETTINGS])
1518 Ekos::DarkLibrary::Instance()->setAllSettings(settings);
1519 KSUtils::setGlobalSettings(settings);
1521 else if(command == commands[DARK_LIBRARY_GET_ALL_SETTINGS])
1522 sendDarkLibrarySettings(Ekos::DarkLibrary::Instance()->getAllSettings());
1523 else if(command == commands[DARK_LIBRARY_GET_DEFECT_SETTINGS])
1524 sendResponse(commands[DARK_LIBRARY_GET_DEFECT_SETTINGS], Ekos::DarkLibrary::Instance()->getDefectSettings());
1525 else if(command == commands[DARK_LIBRARY_SET_CAMERA_PRESETS])
1527 Ekos::DarkLibrary::Instance()->setCameraPresets(payload);
1529 else if (command == commands[DARK_LIBRARY_STOP])
1531 Ekos::DarkLibrary::Instance()->
stop();
1533 else if (command == commands[DARK_LIBRARY_GET_MASTERS_IMAGE])
1535 const int row = payload[
"row"].toInt();
1536 Ekos::DarkLibrary::Instance()->loadIndexInView(row);
1538 else if (command == commands[DARK_LIBRARY_GET_CAMERA_PRESETS])
1540 sendResponse(commands[DARK_LIBRARY_GET_CAMERA_PRESETS], Ekos::DarkLibrary::Instance()->getCameraPresets());
1542 else if (command == commands[DARK_LIBRARY_SET_DEFECT_PIXELS])
1544 Ekos::DarkLibrary::Instance()->setDefectPixels(payload);
1546 else if (command == commands[DARK_LIBRARY_SAVE_MAP])
1548 Ekos::DarkLibrary::Instance()->saveMapB->click();
1550 else if (command == commands[DARK_LIBRARY_SET_DEFECT_FRAME])
1552 Ekos::DarkLibrary::Instance()->setDefectMapEnabled(
false);
1554 else if (command == commands[DARK_LIBRARY_GET_VIEW_MASTERS])
1556 sendResponse(commands[DARK_LIBRARY_GET_VIEW_MASTERS], Ekos::DarkLibrary::Instance()->getViewMasters());
1558 else if (command == commands[DARK_LIBRARY_CLEAR_MASTERS_ROW])
1560 const int rowIndex = payload[
"row"].toInt();
1561 Ekos::DarkLibrary::Instance()->clearRow(rowIndex);
1568void Message::processDeviceCommands(
const QString &command,
const QJsonObject &payload)
1570 QString device = payload[
"device"].toString();
1573 if (device.
isEmpty() && command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1575 m_PropertySubscriptions.clear();
1580 if (!INDIListener::findDevice(device, oneDevice))
1584 if (command == commands[DEVICE_PROPERTY_GET])
1587 if (oneDevice->getJSONProperty(payload[
"property"].toString(), propObject, payload[
"compact"].toBool(
true)))
1588 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
1591 else if (command == commands[DEVICE_PROPERTY_SET])
1593 oneDevice->setJSONProperty(payload[
"property"].
toString(), payload[
"elements"].toArray());
1596 else if (command == commands[DEVICE_GET])
1599 for (
const auto &oneProp : *oneDevice->getProperties())
1602 if (oneDevice->getJSONProperty(oneProp.getName(), singleProp, payload[
"compact"].toBool(
false)))
1612 sendResponse(commands[DEVICE_GET], response);
1616 else if (command == commands[DEVICE_PROPERTY_SUBSCRIBE])
1619 const QJsonArray groups = payload[
"groups"].toArray();
1623 if (m_PropertySubscriptions.contains(device))
1624 props = m_PropertySubscriptions[device];
1629 for (
const auto &oneProp : properties)
1630 props.
insert(oneProp.toString());
1633 else if (groups.
isEmpty() ==
false)
1636 for (
auto &oneProp : *oneDevice->getProperties())
1638 if (indiGroups.contains(oneProp.getGroupName()))
1639 props.
insert(oneProp.getName());
1645 for (
auto &oneProp : *oneDevice->getProperties())
1646 props.
insert(oneProp.getName());
1649 m_PropertySubscriptions[device] = props;
1651 else if (command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1654 const QJsonArray groups = payload[
"groups"].toArray();
1658 if (m_PropertySubscriptions.contains(device))
1659 props = m_PropertySubscriptions[device];
1665 for (
const auto &oneProp : properties)
1666 props.
remove(oneProp.toString());
1669 else if (groups.
isEmpty() ==
false)
1672 for (
auto &oneProp : *oneDevice->getProperties())
1674 if (indiGroups.contains(oneProp.getGroupName()))
1675 props.
remove(oneProp.getName());
1681 for (
auto &oneProp : *oneDevice->getProperties())
1682 props.
remove(oneProp.getName());
1685 m_PropertySubscriptions[device] = props;
1692void Message::processAstronomyCommands(
const QString &command,
const QJsonObject &payload)
1694 if (command == commands[ASTRO_GET_ALMANC])
1701 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
1705 {
"SunRise", almanac.getSunRise()},
1706 {
"SunSet", almanac.getSunSet()},
1707 {
"SunMaxAlt", almanac.getSunMaxAlt()},
1708 {
"SunMinAlt", almanac.getSunMinAlt()},
1709 {
"MoonRise", almanac.getMoonRise()},
1710 {
"MoonSet", almanac.getMoonSet()},
1711 {
"MoonPhase", almanac.getMoonPhase()},
1712 {
"MoonIllum", almanac.getMoonIllum()},
1713 {
"Dawn", almanac.getDawnAstronomicalTwilight()},
1714 {
"Dusk", almanac.getDuskAstronomicalTwilight()},
1718 sendResponse(commands[ASTRO_GET_ALMANC], response);
1720 else if (command == commands[ASTRO_GET_NAMES])
1722 auto composite = KStarsData::Instance()->
skyComposite();
1725 CatalogsDB::CatalogObjectList dsoObjects;
1727 allObjects.
append(composite->objectLists(SkyObject::STAR));
1728 allObjects.
append(composite->objectLists(SkyObject::CATALOG_STAR));
1729 allObjects.
append(composite->objectLists(SkyObject::PLANET));
1730 allObjects.
append(composite->objectLists(SkyObject::MOON));
1731 allObjects.
append(composite->objectLists(SkyObject::COMET));
1732 allObjects.
append(composite->objectLists(SkyObject::ASTEROID));
1733 allObjects.
append(composite->objectLists(SkyObject::SUPERNOVA));
1734 allObjects.
append(composite->objectLists(SkyObject::SATELLITE));
1735 dsoObjects = m_DSOManager.get_objects_all();
1737 for (
auto &oneObject : allObjects)
1738 all << oneObject.second->name() << oneObject.second->longname().split(
", ");
1740 for (
auto &oneObject : dsoObjects)
1741 all << oneObject.name() << oneObject.longname().split(
", ");
1747 else if (command == commands[ASTRO_GET_DESIGNATIONS])
1751 for (
auto &oneObject : m_DSOManager.get_objects_all())
1755 {
"primary", oneObject.name()},
1759 designations.
append(oneDesignation);
1762 sendResponse(commands[ASTRO_GET_DESIGNATIONS], designations);
1764 else if (command == commands[ASTRO_GET_LOCATION])
1766 auto geo = KStarsData::Instance()->
geo();
1769 {
"name",
geo->name()},
1770 {
"longitude",
geo->lng()->Degrees()},
1771 {
"latitude",
geo->lat()->Degrees()},
1772 {
"elevation",
geo->elevation()},
1777 sendResponse(commands[ASTRO_GET_LOCATION], location);
1780 else if (command == commands[ASTRO_SEARCH_OBJECTS])
1783 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
1792 auto objectType =
static_cast<SkyObject::TYPE>(payload[
"type"].toInt(SkyObject::GALAXY));
1794 auto objectDirection =
static_cast<Direction
>(payload[
"direction"].toInt(All));
1796 auto objectMaxMagnitude = payload[
"maxMagnitude"].toDouble(10);
1798 auto objectMinAlt = payload[
"minAlt"].toDouble(15);
1800 auto objectMinDuration = payload[
"minDuration"].toInt(3600);
1802 auto objectMinFOV = payload[
"minFOV"].toDouble(0);
1804 auto *data = KStarsData::Instance();
1806 auto *
geo = KStarsData::Instance()->
geo();
1809 auto start = KStarsData::Instance()->
lt();
1810 auto end = getNextDawn();
1816 CatalogsDB::CatalogObjectList dsoObjects;
1822 case SkyObject::STAR:
1823 case SkyObject::CATALOG_STAR:
1824 allObjects.
append(data->skyComposite()->objectLists(SkyObject::STAR));
1825 allObjects.
append(data->skyComposite()->objectLists(SkyObject::CATALOG_STAR));
1828 case SkyObject::PLANET:
1829 case SkyObject::MOON:
1830 allObjects.
append(data->skyComposite()->objectLists(SkyObject::PLANET));
1831 allObjects.
append(data->skyComposite()->objectLists(SkyObject::MOON));
1834 case SkyObject::COMET:
1835 allObjects.
append(data->skyComposite()->objectLists(SkyObject::COMET));
1837 case SkyObject::ASTEROID:
1838 allObjects.
append(data->skyComposite()->objectLists(SkyObject::ASTEROID));
1841 case SkyObject::OPEN_CLUSTER:
1842 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::OPEN_CLUSTER, objectMaxMagnitude));
1845 case SkyObject::GLOBULAR_CLUSTER:
1846 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GLOBULAR_CLUSTER, objectMaxMagnitude));
1850 case SkyObject::GASEOUS_NEBULA:
1851 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GASEOUS_NEBULA, objectMaxMagnitude));
1854 case SkyObject::PLANETARY_NEBULA:
1855 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::PLANETARY_NEBULA, objectMaxMagnitude));
1858 case SkyObject::GALAXY:
1859 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GALAXY, objectMaxMagnitude));
1862 case SkyObject::SUPERNOVA:
1864 if (!Options::showSupernovae())
1866 Options::setShowSupernovae(
true);
1867 data->setFullTimeUpdate();
1870 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SUPERNOVA));
1873 case SkyObject::SATELLITE:
1875 if (!Options::showSatellites())
1877 Options::setShowSatellites(
true);
1878 data->setFullTimeUpdate();
1881 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SATELLITE));
1889 std::sort(allObjects.
begin(), allObjects.
end(), [](
const auto & a,
const auto & b)
1891 return a.second->mag() < b.second->mag();
1894 QMutableVectorIterator<QPair<QString, const SkyObject *>> objectIterator(allObjects);
1897 if (objectDirection != All)
1899 QPair<int, int> Quardent1(270, 360), Quardent2(0, 90), Quardent3(90, 180), Quardent4(180, 270);
1900 QPair<int, int> minAZ, maxAZ;
1901 switch (objectDirection)
1925 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1926 while (dsoIterator != dsoObjects.end())
1929 const double az = (*dsoIterator).recomputeHorizontalCoords(start, geo).az().Degrees();
1930 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1931 dsoIterator = dsoObjects.erase(dsoIterator);
1938 while (objectIterator.hasNext())
1940 const auto az = objectIterator.next().second->recomputeHorizontalCoords(start, geo).az().Degrees();
1941 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1942 objectIterator.remove();
1950 objectIterator.toFront();
1951 while (objectIterator.hasNext())
1953 auto magnitude = objectIterator.next().second->mag();
1955 if (magnitude != NaN::f && magnitude > objectMaxMagnitude)
1956 objectIterator.remove();
1963 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1964 while (dsoIterator != dsoObjects.end())
1966 double duration = 0;
1969 dms LST =
geo->GSTtoLST(t.gst());
1970 (*dsoIterator).EquatorialToHorizontal(&LST,
geo->lat());
1971 if ((*dsoIterator).alt().Degrees() >= objectMinAlt)
1975 if (duration < objectMinDuration)
1976 dsoIterator = dsoObjects.erase(dsoIterator);
1983 objectIterator.toFront();
1984 while (objectIterator.hasNext())
1986 auto oneObject = objectIterator.next().second;
1987 double duration = 0;
1991 auto LST =
geo->GSTtoLST(t.gst());
1992 const_cast<SkyObject *
>(oneObject)->EquatorialToHorizontal(&LST,
geo->lat());
1993 if (oneObject->alt().Degrees() >= objectMinAlt)
1997 if (duration < objectMinDuration)
1998 objectIterator.remove();
2003 if (isDSO && objectMinFOV > 0)
2005 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
2006 while (dsoIterator != dsoObjects.end())
2008 if ((*dsoIterator).a() < objectMinFOV)
2009 dsoIterator = dsoObjects.erase(dsoIterator);
2016 for (
auto &oneObject : allObjects)
2017 searchObjects.
append(oneObject.second->name());
2018 for (
auto &oneObject : dsoObjects)
2019 searchObjects.
append(oneObject.name());
2024 sendResponse(commands[ASTRO_SEARCH_OBJECTS], response);
2026 else if(command == commands[ASTRO_GET_OBJECT_INFO])
2028 const auto name = payload[
"object"].toString();
2029 bool exact = payload[
"exact"].toBool(
false);
2036 {
"name", exact ?
name : oneObject->
name()},
2038 {
"magnitude", oneObject->
mag()},
2041 {
"ra", oneObject->
ra().
Hours()},
2045 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info);
2054 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info );
2059 else if (command == commands[ASTRO_GET_OBJECTS_INFO])
2062 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2070 bool exact = payload[
"exact"].toBool(
false);
2071 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2074 for (
auto &oneName : objectNames)
2082 {
"name", exact ?
name : oneObject->
name()},
2084 {
"magnitude", oneObject->
mag()},
2087 {
"ra", oneObject->
ra().
Hours()},
2095 info[
"a"] = dsoObject->
a();
2096 info[
"b"] = dsoObject->
b();
2097 info[
"pa"] = dsoObject->
pa();
2100 objectsArray.
append(info);
2104 sendResponse(commands[ASTRO_GET_OBJECTS_INFO], objectsArray);
2107 else if (command == commands[ASTRO_GET_OBJECTS_OBSERVABILITY])
2110 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2118 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2121 bool exact = payload[
"exact"].toBool(
false);
2123 auto *data = KStarsData::Instance();
2125 auto *
geo = KStarsData::Instance()->
geo();
2127 auto ut = data->ut();
2129 for (
auto &oneName : objectNames)
2132 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2136 dms ha(data->lst()->Degrees() - oneObject->
ra().
Degrees());
2139 {
"name", exact ?
name : oneObject->
name()},
2145 objectsArray.
append(info);
2149 sendResponse(commands[ASTRO_GET_OBJECTS_OBSERVABILITY], objectsArray);
2151 else if (command == commands[ASTRO_GET_OBJECTS_RISESET])
2154 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2162 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2165 bool exact = payload[
"exact"].toBool(
false);
2167 auto *data = KStarsData::Instance();
2169 auto *
geo = KStarsData::Instance()->
geo();
2175 if (data->lt().time().hour() > 12)
2178 for (
auto &oneName : objectNames)
2181 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2191 if (transitTime < riseTime)
2198 if (setTime < riseTime)
2201 info[
"name"] = exact ?
name : oneObject->
name();
2211 info[
"rise"] =
"Circumpolar";
2212 info[
"set"] =
"Circumpolar";
2216 info[
"rise"] =
"Never rises";
2217 info[
"set"] =
"Never rises";
2224 for (
double h = -12.0; h <= 12.0; h += 0.5)
2226 double hour = h + (24.0 * DayOffset);
2233 info[
"altitudes"] = altitudes;
2235 objectsArray.
append(info);
2239 sendResponse(commands[ASTRO_GET_OBJECTS_RISESET], objectsArray);
2253 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
2257 if (nextDawn < localTime)
2266void Message::requestDSLRInfo(
const QString &cameraName)
2268 sendResponse(commands[DSLR_GET_INFO], cameraName);
2274void Message::requestPortSelection(
bool show)
2276 sendResponse(commands[GET_PROFILE_PORT_SELECTION], show);
2282void Message::sendDialog(
const QJsonObject &message)
2284 sendResponse(commands[DIALOG_GET_INFO], message);
2292 for (
auto &nodeManager : m_NodeManagers)
2294 nodeManager->message()->sendResponse(command, payload);
2303 for (
auto &nodeManager : m_NodeManagers)
2305 nodeManager->message()->sendResponse(command, payload);
2312void Message::sendResponse(
const QString &command,
const QString &payload)
2314 for (
auto &nodeManager : m_NodeManagers)
2316 nodeManager->message()->sendResponse(command, payload);
2323void Message::sendResponse(
const QString &command,
bool payload)
2325 for (
auto &nodeManager : m_NodeManagers)
2327 nodeManager->message()->sendResponse(command, payload);
2334void Message::autofocusAborted()
2338 {
"status",
"Aborted"}
2340 sendResponse(commands[NEW_FOCUS_STATE], cStatus);
2346void Message::updateMountStatus(
const QJsonObject &status,
bool throttle)
2351 if (m_ThrottleTS.msecsTo(now) >= THROTTLE_INTERVAL)
2354 sendResponse(commands[NEW_MOUNT_STATE], status);
2358 sendResponse(commands[NEW_MOUNT_STATE], status);
2364void Message::updateCaptureStatus(
const QJsonObject &status)
2366 sendResponse(commands[NEW_CAPTURE_STATE], status);
2372void Message::updateFocusStatus(
const QJsonObject &status)
2374 sendResponse(commands[NEW_FOCUS_STATE], status);
2380void Message::updateGuideStatus(
const QJsonObject &status)
2382 sendResponse(commands[NEW_GUIDE_STATE], status);
2388void Message::updateDomeStatus(
const QJsonObject &status)
2390 sendResponse(commands[NEW_DOME_STATE], status);
2396void Message::updateCapStatus(
const QJsonObject &status)
2398 sendResponse(commands[NEW_CAP_STATE], status);
2404void Message::updateAlignStatus(
const QJsonObject &status)
2406 sendResponse(commands[NEW_ALIGN_STATE], status);
2412void Message::sendConnection()
2416 {
"connected",
true},
2417 {
"online", m_Manager->getEkosStartingStatus() == Ekos::Success}
2420 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
2426void Message::sendStates()
2429 if (m_Manager->captureModule())
2431 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2432 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2433 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2436 if (m_Manager->mountModule())
2440 {
"status", m_Manager->mountModule()->statusString(
false)},
2441 {
"target", m_Manager->capturePreview->mountTarget->text()},
2442 {
"slewRate", m_Manager->mountModule()->slewRate()},
2443 {
"pierSide", m_Manager->mountModule()->pierSide()}
2446 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2449 if (m_Manager->focusModule())
2451 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2452 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2455 if (m_Manager->guideModule())
2457 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2458 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2461 if (m_Manager->alignModule())
2466 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2468 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2471 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2478 doc.
setHtml(paa->getPAHMessage());
2481 {
"stage", paa->getPAHStageString(
false)},
2485 sendResponse(commands[NEW_POLAR_STATE], polarState);
2493void Message::sendEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
2495 if (Options::ekosLiveNotifications() ==
false)
2501 {
"severity",
event},
2502 {
"message", message},
2506 sendResponse(commands[NEW_NOTIFICATION], newEvent);
2512void Message::sendManualRotatorStatus(
double currentPA,
double targetPA,
double threshold)
2514 QJsonObject request = {{
"currentPA", currentPA}, {
"targetPA", targetPA}, {
"threshold", threshold}};
2515 sendResponse(commands[ALIGN_MANUAL_ROTATOR_STATUS], request);
2521void Message::setBoundingRect(
QRect rect,
QSize view,
double currentZoom)
2523 m_BoundingRect = rect;
2525 m_CurrentZoom = currentZoom;
2531void Message::processDialogResponse(
const QJsonObject &payload)
2539void Message::processNewProperty(INDI::Property prop)
2544 if (m_Manager->settleStatus() != Ekos::CommunicationStatus::Success)
2548 ISD::propertyToJson(prop, propObject,
false);
2549 sendResponse(commands[DEVICE_PROPERTY_ADD], propObject);
2555void Message::processDeleteProperty(INDI::Property prop)
2559 {
"device", prop.getDeviceName()},
2560 {
"name", prop.getName()}
2563 sendResponse(commands[DEVICE_PROPERTY_REMOVE], payload);
2571 if (Options::ekosLiveNotifications() ==
false)
2577 {
"device", device->getDeviceName()},
2578 {
"message", message}
2581 sendResponse(commands[DEVICE_MESSAGE], payload);
2587void Message::processUpdateProperty(INDI::Property prop)
2589 if (m_PropertySubscriptions.contains(prop.getDeviceName()))
2591 QSet<QString> subProps = m_PropertySubscriptions[prop.getDeviceName()];
2592 if (subProps.
contains(prop.getName()))
2594 m_PendingProperties.remove(prop);
2595 m_PendingProperties.insert(prop);
2603void Message::setPendingPropertiesEnabled(
bool enabled)
2606 m_PendingPropertiesTimer.start();
2609 m_PendingProperties.clear();
2611 if (m_PendingPropertiesTimer.isActive())
2613 m_PendingPropertiesTimer.stop();
2614 std::this_thread::sleep_for(std::chrono::milliseconds(500));
2622void Message::sendPendingProperties()
2624 for (
auto &prop : m_PendingProperties)
2626 if (prop->isValid())
2629 ISD::propertyToJson(*prop, propObject);
2630 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
2634 m_PendingProperties.clear();
2640void Message::sendModuleState(
const QString &name)
2642 if (name ==
"Capture")
2644 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2645 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2646 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2648 else if (name ==
"Mount")
2652 {
"status", m_Manager->mountStatus->getStatusText()},
2653 {
"target", m_Manager->capturePreview->mountTarget->text()},
2654 {
"slewRate", m_Manager->mountModule()->slewRate()},
2655 {
"pierSide", m_Manager->mountModule()->pierSide()}
2658 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2660 else if (name ==
"Focus")
2662 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2663 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2665 else if (name ==
"Guide")
2667 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2668 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2670 else if (name ==
"Align")
2675 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2677 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2680 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2687 doc.
setHtml(paa->getPAHMessage());
2690 {
"stage", paa->getPAHStageString(
false)},
2694 sendResponse(commands[NEW_POLAR_STATE], polarState);
2706 if (name ==
"Manager")
2720 for (
auto &tab : viewer->tabs())
2722 if (tab->getView()->objectName() == name)
2723 return tab->getView().get();
2736#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2737bool Message::parseArgument(
QVariant::Type type,
const QVariant &arg, QMetaMethodArgument &genericArg, SimpleTypes &types)
2746 case QVariant::Type::Int:
2747 types.number_integer = arg.
toInt();
2748 genericArg = Q_ARG(
int, types.number_integer);
2750 case QVariant::Type::UInt:
2751 types.number_unsigned_integer = arg.
toUInt();
2752 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2754 case QVariant::Type::LongLong:
2756 genericArg = Q_ARG(
int, types.number_integer);
2758 case QVariant::Type::ULongLong:
2759 types.number_unsigned_integer = arg.
toULongLong();
2760 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2762 case QVariant::Type::Double:
2763 types.number_double = arg.
toDouble();
2764 genericArg = Q_ARG(
double, types.number_double);
2766 case QVariant::Type::Bool:
2767 types.boolean = arg.
toBool();
2768 genericArg = Q_ARG(
bool, types.boolean);
2770 case QVariant::Type::String:
2772 genericArg = Q_ARG(
QString, types.text);
2774 case QVariant::Type::Url:
2775 types.url = arg.
toUrl();
2776 genericArg = Q_ARG(
QUrl, types.
url);
2790#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2798 auto name = payload[
"name"].toString().toLatin1();
2804 for (
auto oneArg : args)
2806 auto argObject = oneArg.toObject();
2807#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2808 QMetaMethodArgument genericArgument;
2812 SimpleTypes genericType;
2813 argsList.
append(genericArgument);
2814 typesList.
append(genericType);
2815 if (parseArgument(
static_cast<QVariant::Type>(argObject[
"type"].toInt()), argObject[
"value"].toVariant(), argsList.
back(),
2816 typesList.
last()) ==
false)
2823 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.
const double & Degrees() const
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.
QString name(GameStandardAction id)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
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)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
void setCurrentIndex(int index)
QDateTime currentDateTime()
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