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>
46Message::Message(Ekos::Manager *manager, QVector<QSharedPointer<NodeManager>> &nodeManagers):
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);
57 connect(INDIListener::Instance(), &INDIListener::deviceRemoved,
64 const auto &pending = it.next();
65 if (pending.device == device->getDeviceName())
72 m_PendingPropertiesTimer.setInterval(500);
75 m_DebouncedSend.setInterval(500);
82void Message::onConnected()
84 auto node = qobject_cast<Node*>(sender());
88 qCInfo(KSTARS_EKOS) <<
"Connected to Message Websocket server at" << node->url().toDisplayString();
90 m_PendingPropertiesTimer.start();
99void Message::onDisconnected()
101 auto node = qobject_cast<Node*>(sender());
105 qCInfo(KSTARS_EKOS) <<
"Disconnected from Message Websocket server at" << node->url().toDisplayString();
107 if (isConnected() ==
false)
109 m_PendingPropertiesTimer.stop();
117void Message::onTextReceived(
const QString &message)
119 auto node = qobject_cast<Node*>(sender());
120 if (!node || message.
isEmpty())
123 qCInfo(KSTARS_EKOS) <<
"Websocket Message" << message;
128 qCWarning(KSTARS_EKOS) <<
"Ekos Live Parsing Error" <<
error.errorString();
133 const QString command = msgObj[
"type"].toString();
134 const QJsonObject payload = msgObj[
"payload"].toObject();
136 if (command == commands[GET_CONNECTION])
140 else if (command == commands[LOGOUT] || command == commands[SESSION_EXPIRED])
142 emit expired(node->url());
145 else if (command == commands[SET_CLIENT_STATE])
148 if (payload[
"state"].toBool(
false))
150 qCInfo(KSTARS_EKOS) <<
"EkosLive client is connected.";
153 if (KStarsData::Instance()->clock()->isActive() ==
false)
155 qCInfo(KSTARS_EKOS) <<
"Resuming and syncing clock.";
156 KStarsData::Instance()->clock()->start();
166 qCInfo(KSTARS_EKOS) <<
"EkosLive client is disconnected.";
168 if (
KStars::Instance()->isStartedWithClockRunning() ==
false && m_Manager->ekosStatus() == Ekos::CommunicationStatus::Idle)
170 qCInfo(KSTARS_EKOS) <<
"Stopping the clock.";
171 KStarsData::Instance()->clock()->stop();
175 else if (command == commands[GET_DRIVERS])
177 else if (command == commands[GET_PROFILES])
179 else if (command == commands[GET_SCOPES])
181 else if (command == commands[GET_DSLR_LENSES])
183 else if(command == commands[INVOKE_METHOD])
185 auto object = findObject(payload[
"object"].
toString());
187 invokeMethod(
object, payload);
189 else if(command == commands[SET_PROPERTY])
191 auto object = findObject(payload[
"object"].
toString());
193 object->setProperty(payload[
"name"].
toString().toLatin1().constData(), payload[
"value"].toVariant());
195 else if(command == commands[GET_PROPERTY])
197 auto map = QVariantMap();
198 map[
"result"] =
false;
199 auto object = findObject(payload[
"object"].
toString());
202 auto value =
object->property(payload[
"name"].
toString().toLatin1().constData());
205 map[
"result"] =
true;
206 map[
"value"] = value;
211 else if (command == commands[TRAIN_GET_ALL])
213 else if (command == commands[TRAIN_SETTINGS_GET])
215 auto id = payload[
"id"].toInt(-1);
218 Ekos::OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
219 auto settings = Ekos::OpticalTrainSettings::Instance()->getSettings();
220 if (!settings.isEmpty())
225 processScopeCommands(command, payload);
227 processProfileCommands(command, payload);
229 processAstronomyCommands(command, payload);
230 else if (command == commands[DIALOG_GET_RESPONSE])
231 processDialogResponse(payload);
233 processOptionsCommands(command, payload);
235 processSchedulerCommands(command, payload);
237 processDSLRCommands(command, payload);
239 processFileCommands(command, payload);
241 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
244 if (command == commands[GET_STATES])
246 else if (command == commands[GET_STELLARSOLVER_PROFILES])
247 sendStellarSolverProfiles();
248 else if (command == commands[GET_DEVICES])
251 processCaptureCommands(command, payload);
253 processMountCommands(command, payload);
255 processFocusCommands(command, payload);
257 processGuideCommands(command, payload);
259 processAlignCommands(command, payload);
261 processPolarCommands(command, payload);
263 processTrainCommands(command, payload);
265 processFilterManagerCommands(command, payload);
267 processDarkLibraryCommands(command, payload);
269 processDeviceCommands(command, payload);
276bool Message::isConnected()
const
278 return std::any_of(m_NodeManagers.begin(), m_NodeManagers.end(), [](
auto & nodeManager)
280 return nodeManager->message()->isConnected();
287void Message::sendStellarSolverProfiles()
289 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
294 if (m_Manager->focusModule())
299 if (m_Manager->alignModule())
303 sendResponse(commands[GET_STELLARSOLVER_PROFILES], profiles);
309void Message::sendDrivers()
311 sendResponse(commands[GET_DRIVERS], DriverManager::Instance()->getDriverList());
317void Message::sendDevices()
319 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
324 for(
auto &gd : INDIListener::devices())
328 {
"name", gd->getDeviceName()},
329 {
"connected", gd->isConnected()},
330 {
"version", gd->getDriverVersion()},
331 {
"interface",
static_cast<int>(gd->getDriverInterface())},
334 deviceList.
append(oneDevice);
337 sendResponse(commands[GET_DEVICES], deviceList);
343void Message::sendTrains()
347 for(
auto &train : Ekos::OpticalTrainManager::Instance()->getOpticalTrains())
350 sendResponse(commands[TRAIN_GET_ALL], trains);
356void Message::sendTrainProfiles()
358 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
361 auto profiles = Ekos::ProfileSettings::Instance()->getSettings();
369void Message::requestOpticalTrains(
bool show)
371 sendResponse(commands[TRAIN_CONFIGURATION_REQUESTED], show);
377void Message::sendScopes()
382 KStarsData::Instance()->userdb()->GetAllScopes(allScopes);
384 for (
auto &scope : allScopes)
385 scopeList.
append(scope->toJson());
387 sendResponse(commands[GET_SCOPES], scopeList);
393void Message::sendDSLRLenses()
398 KStarsData::Instance()->userdb()->GetAllDSLRLenses(allDslrLens);
400 for (
auto &dslrLens : allDslrLens)
401 dslrList.
append(dslrLens->toJson());
403 sendResponse(commands[GET_DSLR_LENSES], dslrList);
409void Message::sendTemperature(
double value)
417 {
"name", oneCCD->getDeviceName()},
418 {
"temperature", value}
421 sendResponse(commands[NEW_CAMERA_STATE], temperature);
428void Message::processCaptureCommands(
const QString &command,
const QJsonObject &payload)
430 auto capture = m_Manager->captureModule();
432 if (capture ==
nullptr)
434 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as capture module is not available";
438 if (command == commands[CAPTURE_PREVIEW])
440 capture->mainCamera()->capturePreview();
442 else if (command == commands[CAPTURE_TOGGLE_VIDEO])
444 capture->setVideoLimits(payload[
"maxBufferSize"].toInt(512), payload[
"maxPreviewFPS"].toInt(10));
445 capture->toggleVideo(payload[
"enabled"].toBool());
447 else if (command == commands[CAPTURE_START])
449 else if (command == commands[CAPTURE_STOP])
451 else if (command == commands[CAPTURE_LOOP])
453 capture->mainCamera()->startFraming();
455 else if (command == commands[CAPTURE_GET_SEQUENCES])
457 sendCaptureSequence(capture->getSequence());
459 else if (command == commands[CAPTURE_ADD_SEQUENCE])
462 capture->mainCamera()->createJob();
464 else if (command == commands[CAPTURE_REMOVE_SEQUENCE])
466 if (capture->mainCamera()->removeJob(payload[
"index"].toInt()) ==
false)
467 sendCaptureSequence(capture->getSequence());
469 else if (command == commands[CAPTURE_CLEAR_SEQUENCES])
471 capture->clearSequenceQueue();
473 else if (command == commands[CAPTURE_SAVE_SEQUENCE_FILE])
475 if (capture->saveSequenceQueue(payload[
"filepath"].toString()))
478 else if (command == commands[CAPTURE_LOAD_SEQUENCE_FILE])
493 path = payload[
"filepath"].toString();
497 auto result = capture->loadSequenceQueue(path);
503 sendResponse(commands[CAPTURE_LOAD_SEQUENCE_FILE], response);
506 else if (command == commands[CAPTURE_GET_ALL_SETTINGS])
508 sendCaptureSettings(capture->mainCamera()->getAllSettings());
510 else if (command == commands[CAPTURE_SET_ALL_SETTINGS])
513 capture->mainCamera()->setAllSettings(settings);
514 KSUtils::setGlobalSettings(settings);
516 else if (command == commands[CAPTURE_GENERATE_DARK_FLATS])
518 capture->mainCamera()->generateDarkFlats();
525void Message::sendCaptureSequence(
const QJsonArray &sequenceArray)
527 sendResponse(commands[CAPTURE_GET_SEQUENCES], sequenceArray);
530void Message::sendPreviewLabel(
const QString &preview)
536 sendResponse(commands[CAPTURE_GET_PREVIEW_LABEL], payload);
542void Message::sendCaptureSettings(
const QVariantMap &settings)
544 m_DebouncedSend.start();
545 m_DebouncedMap[commands[CAPTURE_GET_ALL_SETTINGS]] = settings;
551void Message::sendAlignSettings(
const QVariantMap &settings)
553 m_DebouncedSend.start();
554 m_DebouncedMap[commands[ALIGN_GET_ALL_SETTINGS]] = settings;
560void Message::sendGuideSettings(
const QVariantMap &settings)
562 m_DebouncedSend.start();
563 m_DebouncedMap[commands[GUIDE_GET_ALL_SETTINGS]] = settings;
570void Message::sendFocusSettings(
const QVariantMap &settings)
572 m_DebouncedSend.start();
573 m_DebouncedMap[commands[FOCUS_GET_ALL_SETTINGS]] = settings;
579void Message::sendMountSettings(
const QVariantMap &settings)
581 m_DebouncedSend.start();
582 m_DebouncedMap[commands[MOUNT_GET_ALL_SETTINGS]] = settings;
588void Message::sendDarkLibrarySettings(
const QVariantMap &settings)
590 m_DebouncedSend.start();
591 m_DebouncedMap[commands[DARK_LIBRARY_GET_ALL_SETTINGS]] = settings;
598void Message::sendSchedulerSettings(
const QVariantMap &settings)
600 m_DebouncedSend.start();
601 m_DebouncedMap[commands[SCHEDULER_GET_ALL_SETTINGS]] = settings;
607void Message::dispatchDebounceQueue()
615 m_DebouncedMap.clear();
618 Options::self()->save();
628 if (guide ==
nullptr)
630 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as guide module is not available";
634 if (command == commands[GUIDE_START])
638 else if (command == commands[GUIDE_CAPTURE])
640 else if (command == commands[GUIDE_LOOP])
642 else if (command == commands[GUIDE_STOP])
644 else if (command == commands[GUIDE_CLEAR])
646 else if (command == commands[GUIDE_SET_ALL_SETTINGS])
649 guide->setAllSettings(settings);
650 KSUtils::setGlobalSettings(settings);
652 else if (command == commands[GUIDE_GET_ALL_SETTINGS])
653 sendGuideSettings(guide->getAllSettings());
654 else if(command == commands[GUIDE_SET_CALIBRATION_SETTINGS])
657 Options::setCalibrationPulseDuration(payload[
"pulse"].toInt());
658 Options::setGuideCalibrationBacklash(payload[
"max_move"].toInt());
659 Options::setTwoAxisEnabled(payload[
"two_axis"].toBool());
660 Options::setGuideAutoSquareSizeEnabled(payload[
"square_size"].toBool());
661 Options::setGuideCalibrationBacklash(payload[
"calibrationBacklash"].toBool());
662 Options::setResetGuideCalibration(payload[
"resetCalibration"].toBool());
663 Options::setReuseGuideCalibration(payload[
"reuseCalibration"].toBool());
664 Options::setReverseDecOnPierSideChange(payload[
"reverseCalibration"].toBool());
665 sendGuideSettings(m_Manager->guideModule()->getAllSettings());
675 if (m_Manager->focusModule())
676 focus = m_Manager->focusModule()->mainFocuser();
680 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as focus module is not available";
684 if (command == commands[FOCUS_START])
686 else if (command == commands[FOCUS_CAPTURE])
691 else if (command == commands[FOCUS_STOP])
693 else if (command == commands[FOCUS_RESET])
695 else if (command == commands[FOCUS_IN])
696 focus->focusIn(payload[
"steps"].toInt());
697 else if (command == commands[FOCUS_OUT])
698 focus->focusOut(payload[
"steps"].toInt());
699 else if (command == commands[FOCUS_LOOP])
700 focus->startFraming();
701 else if (command == commands[FOCUS_SET_ALL_SETTINGS])
704 focus->setAllSettings(settings);
705 KSUtils::setGlobalSettings(settings);
708 else if (command == commands[FOCUS_GET_ALL_SETTINGS])
709 sendFocusSettings(focus->getAllSettings());
710 else if (command == commands[FOCUS_SET_CROSSHAIR])
712 double x = payload[
"x"].toDouble();
713 double y = payload[
"y"].toDouble();
714 focus->selectFocusStarFraction(x, y);
725 if (mount ==
nullptr)
727 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as mount module is not available";
731 if (command == commands[MOUNT_ABORT])
733 else if (command == commands[MOUNT_PARK])
735 else if (command == commands[MOUNT_UNPARK])
737 else if (command == commands[MOUNT_SET_TRACKING])
738 mount->setTrackEnabled(payload[
"enabled"].toBool());
739 else if (command == commands[MOUNT_SYNC_RADE])
741 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
744 mount->sync(ra.Hours(), de.Degrees());
746 else if (command == commands[MOUNT_SYNC_TARGET])
750 else if (command == commands[MOUNT_GOTO_RADE])
752 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
755 mount->slew(ra.Hours(), de.Degrees());
757 else if (command == commands[MOUNT_GOTO_TARGET])
761 else if (command == commands[MOUNT_SET_SLEW_RATE])
763 int rate = payload[
"rate"].toInt(-1);
765 mount->setSlewRate(rate);
767 else if (command == commands[MOUNT_SET_ALL_SETTINGS])
770 mount->setAllSettings(settings);
771 KSUtils::setGlobalSettings(settings);
773 else if (command == commands[MOUNT_GET_ALL_SETTINGS])
774 sendMountSettings(
mount->getAllSettings());
775 else if (command == commands[MOUNT_SET_MOTION])
777 QString direction = payload[
"direction"].toString();
778 ISD::Mount::MotionCommand action = payload[
"action"].toBool(
false) ?
779 ISD::Mount::MOTION_START : ISD::Mount::MOTION_STOP;
781 if (direction ==
"N")
782 mount->motionCommand(action, ISD::Mount::MOTION_NORTH, -1);
783 else if (direction ==
"S")
784 mount->motionCommand(action, ISD::Mount::MOTION_SOUTH, -1);
785 else if (direction ==
"E")
786 mount->motionCommand(action, -1, ISD::Mount::MOTION_EAST);
787 else if (direction ==
"W")
788 mount->motionCommand(action, -1, ISD::Mount::MOTION_WEST);
790 else if (command == commands[MOUNT_GOTO_PIXEL])
792 const auto name = payload[
"camera"].toString();
793 const auto xFactor = payload[
"x"].toDouble();
794 const auto yFactor = payload[
"y"].toDouble();
796 for(
auto &oneDevice : INDIListener::devices())
798 auto camera = oneDevice->getCamera();
799 if (!camera || camera->getDeviceName() != name)
802 auto primaryChip = camera->getChip(ISD::CameraChip::PRIMARY_CCD);
807 auto imageData = primaryChip->getImageData();
808 if (!imageData || imageData->hasWCS() ==
false)
811 auto x = xFactor * imageData->width();
812 auto y = yFactor * imageData->height();
816 if (imageData->pixelToWCS(point, coord))
820 mount->gotoTarget(coord);
825 else if (command == commands[MOUNT_TOGGLE_AUTOPARK])
826 mount->setAutoParkEnabled(payload[
"toggled"].toBool());
836 if (align ==
nullptr)
838 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as align module is not available";
842 if (command == commands[ALIGN_SOLVE])
846 else if (command == commands[ALIGN_SET_ALL_SETTINGS])
849 align->setAllSettings(settings);
850 KSUtils::setGlobalSettings(settings);
852 else if (command == commands[ALIGN_GET_ALL_SETTINGS])
853 sendAlignSettings(align->getAllSettings());
854 else if(command == commands[ALIGN_SET_ASTROMETRY_SETTINGS])
856 Options::setAstrometryRotatorThreshold(payload[
"threshold"].toInt());
857 Options::setAstrometryUseRotator(payload[
"rotator_control"].toBool());
858 Options::setAstrometryUseImageScale(payload[
"scale"].toBool());
859 Options::setAstrometryUsePosition(payload[
"position"].toBool());
861 else if (command == commands[ALIGN_STOP])
863 else if (command == commands[ALIGN_LOAD_AND_SLEW])
882 else if (command == commands[ALIGN_MANUAL_ROTATOR_TOGGLE])
884 align->toggleManualRotator(payload[
"toggled"].toBool());
893 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
901 sendResponse(commands[NEW_ALIGN_STATE], alignState);
907void Message::setAlignSolution(
const QVariantMap &solution)
909 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
917 sendResponse(commands[NEW_ALIGN_STATE], alignState);
923void Message::processSchedulerCommands(
const QString &command,
const QJsonObject &payload)
927 if (command == commands[SCHEDULER_GET_JOBS])
931 else if (command == commands[SCHEDULER_ADD_JOBS])
935 else if(command == commands[SCHEDULER_REMOVE_JOBS])
937 int index = payload[
"index"].toInt();
940 else if(command == commands[SCHEDULER_GET_ALL_SETTINGS])
942 sendSchedulerSettings(scheduler->getAllSettings());
944 else if(command == commands[SCHEDULER_SET_ALL_SETTINGS])
947 scheduler->setAllSettings(settings);
948 KSUtils::setGlobalSettings(settings);
950 else if (command == commands[SCHEDULER_SAVE_FILE])
955 else if (command == commands[SCHEDULER_SAVE_SEQUENCE_FILE])
976 sendResponse(commands[SCHEDULER_SAVE_SEQUENCE_FILE], response);
978 else if (command == commands[SCHEDULER_LOAD_FILE])
989 if (!tempFile.
open())
1008 file.
write(payload[
"filedata"].toString().toUtf8()) == -1)
1027 response[
"path"] =
path;
1030 sendResponse(commands[SCHEDULER_LOAD_FILE], response);
1032 else if(command == commands[SCHEDULER_START_JOB])
1034 scheduler->toggleScheduler();
1036 else if(command == commands[SCHEDULER_IMPORT_MOSAIC])
1039 sendSchedulerJobs();
1041 sendEvent(
i18n(
"Mosaic import failed."), KSNotification::Scheduler, KSNotification::Alert);
1048void Message::processPolarCommands(
const QString &command,
const QJsonObject &payload)
1056 if (command == commands[PAH_START])
1058 paa->startPAHProcess();
1060 if (command == commands[PAH_STOP])
1062 paa->stopPAHProcess();
1064 else if (command == commands[PAH_REFRESH])
1066 paa->setPAHRefreshDuration(payload[
"value"].toDouble(1));
1067 paa->startPAHRefreshProcess();
1069 else if (command == commands[PAH_SET_ALGORITHM])
1073 algorithmCombo->
setCurrentIndex(
static_cast<Ekos::PolarAlignmentAssistant::RefreshAlgorithm
>(payload[
"value"].toInt(1)));
1075 else if (command == commands[PAH_RESET_VIEW])
1077 emit resetPolarView();
1079 else if (command == commands[PAH_SET_CROSSHAIR])
1081 double x = payload[
"x"].toDouble();
1082 double y = payload[
"y"].toDouble();
1084 if (m_BoundingRect.isNull() ==
false)
1088 double boundX = x * m_BoundingRect.width();
1089 double boundY = y * m_BoundingRect.height();
1094 x = ((boundX + m_BoundingRect.x()) / (m_CurrentZoom / 100)) / m_ViewSize.width();
1095 y = ((boundY + m_BoundingRect.y()) / (m_CurrentZoom / 100)) / m_ViewSize.height();
1099 paa->setPAHCorrectionOffsetPercentage(x, y);
1101 else if (command == commands[PAH_SELECT_STAR_DONE])
1107 else if (command == commands[PAH_REFRESHING_DONE])
1109 paa->stopPAHProcess();
1111 else if (command == commands[PAH_SLEW_DONE])
1113 paa->setPAHSlewDone();
1115 else if (command == commands[PAH_PAH_SET_ZOOM])
1117 double scale = payload[
"scale"].toDouble();
1118 align->setAlignZoom(scale);
1126void Message::setPAHStage(Ekos::PolarAlignmentAssistant::Stage stage)
1128 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1141 {
"stage", paa->getPAHStageString(
false)}
1146 if (stage == Ekos::PolarAlignmentAssistant::PAH_STAR_SELECT)
1147 align->zoomAlignView();
1149 sendResponse(commands[NEW_POLAR_STATE], polarState);
1155void Message::setPAHMessage(
const QString &message)
1157 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1167 sendResponse(commands[NEW_POLAR_STATE], polarState);
1173void Message::setPolarResults(
QLineF correctionVector,
double polarError,
double azError,
double altError)
1175 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1178 this->correctionVector = correctionVector;
1183 {
"center_x",
center.x()},
1184 {
"center_y",
center.y()},
1185 {
"mag", correctionVector.
length()},
1186 {
"pa", correctionVector.
angle()},
1187 {
"error", polarError},
1188 {
"azError", azError},
1189 {
"altError", altError}
1197 sendResponse(commands[NEW_POLAR_STATE], polarState);
1203void Message::setUpdatedErrors(
double total,
double az,
double alt)
1205 if (isConnected() ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1210 {
"updatedError", total},
1211 {
"updatedAZError", az},
1212 {
"updatedALTError", alt}
1215 sendResponse(commands[NEW_POLAR_STATE], error);
1221void Message::setPAHEnabled(
bool enabled)
1223 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
1228 {
"enabled", enabled}
1231 sendResponse(commands[NEW_POLAR_STATE], polarState);
1237void Message::processProfileCommands(
const QString &command,
const QJsonObject &payload)
1239 if (command == commands[START_PROFILE])
1241 if (m_Manager->getEkosStartingStatus() != Ekos::Idle)
1244 m_Manager->setProfile(payload[
"name"].
toString());
1249 else if (command == commands[STOP_PROFILE])
1256 m_PropertySubscriptions.clear();
1258 else if (command == commands[ADD_PROFILE])
1260 m_Manager->addNamedProfile(payload);
1263 else if (command == commands[UPDATE_PROFILE])
1265 m_Manager->editNamedProfile(payload);
1268 else if (command == commands[GET_PROFILE])
1270 m_Manager->getNamedProfile(payload[
"name"].
toString());
1272 else if (command == commands[DELETE_PROFILE])
1274 m_Manager->deleteNamedProfile(payload[
"name"].
toString());
1277 else if (command == commands[SET_PROFILE_MAPPING])
1279 m_Manager->setProfileMapping(payload);
1281 else if (command == commands[SET_PROFILE_PORT_SELECTION])
1283 requestPortSelection(
false);
1284 m_Manager->acceptPortSelection();
1291void Message::sendProfiles()
1296 if (!m_Manager->getCurrentProfile(profile))
1299 for (
auto &oneProfile : m_Manager->profiles)
1300 profileArray.
append(oneProfile->toJson());
1304 {
"selectedProfile", profile->name},
1305 {
"profiles", profileArray}
1307 sendResponse(commands[GET_PROFILES], profiles);
1313void Message::sendSchedulerJobs()
1317 {
"jobs", m_Manager->schedulerModule()->moduleState()->getJSONJobs()}
1319 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1325void Message::sendSchedulerJobList(
QJsonArray jobsList)
1331 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1337void Message::sendSchedulerStatus(
const QJsonObject &status)
1339 sendResponse(commands[NEW_SCHEDULER_STATE], status);
1346void Message::setEkosStatingStatus(Ekos::CommunicationStatus status)
1348 if (status == Ekos::Pending)
1353 {
"connected",
true},
1354 {
"online",
status == Ekos::Success}
1356 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
1362void Message::setINDIStatus(Ekos::CommunicationStatus status)
1369 sendResponse(commands[NEW_INDI_STATE], connectionState);
1375void Message::processOptionsCommands(
const QString &command,
const QJsonObject &payload)
1377 if (command == commands[OPTION_SET])
1379 const QJsonArray options = payload[
"options"].toArray();
1380 for (
const auto &oneOption : options)
1381 Options::self()->setProperty(oneOption[
QString(
"name")].
toString().toLatin1(), oneOption[
QString(
"value")].toVariant());
1383 Options::self()->save();
1384 emit optionsUpdated();
1386 else if (command == commands[OPTION_GET])
1390 for (
const auto &oneOption : options)
1392 const auto name = oneOption[
QString(
"name")].toString();
1396 map[
"value"] = value;
1399 sendResponse(commands[OPTION_GET], result);
1406void Message::processScopeCommands(
const QString &command,
const QJsonObject &payload)
1408 if (command == commands[ADD_SCOPE])
1410 KStarsData::Instance()->userdb()->AddScope(payload[
"model"].
toString(), payload[
"vendor"].
toString(),
1411 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble());
1413 else if (command == commands[UPDATE_SCOPE])
1415 KStarsData::Instance()->userdb()->AddScope(payload[
"model"].
toString(), payload[
"vendor"].
toString(),
1416 payload[
"type"].
toString(), payload[
"aperture"].toDouble(), payload[
"focal_length"].toDouble(), payload[
"id"].
toString());
1418 else if (command == commands[DELETE_SCOPE])
1420 KStarsData::Instance()->userdb()->DeleteEquipment(
"telescope", payload[
"id"].
toString());
1431 if (command == commands[DSLR_SET_INFO])
1433 if (m_Manager->captureModule())
1434 m_Manager->captureModule()->mainCamera()->addDSLRInfo(
1436 payload[
"width"].toInt(),
1437 payload[
"height"].toInt(),
1438 payload[
"pixelw"].toDouble(),
1439 payload[
"pixelh"].toDouble());
1442 else if(command == commands[DSLR_ADD_LENS])
1444 KStarsData::Instance()->userdb()->AddDSLRLens(payload[
"model"].
toString(), payload[
"vendor"].
toString(),
1445 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble());
1447 else if (command == commands[DSLR_DELETE_LENS])
1449 KStarsData::Instance()->userdb()->DeleteEquipment(
"dslrlens", payload[
"id"].
toString());
1451 else if (command == commands[DSLR_UPDATE_LENS])
1453 KStarsData::Instance()->userdb()->AddDSLRLens(payload[
"model"].
toString(), payload[
"vendor"].
toString(),
1454 payload[
"focal_length"].toDouble(), payload[
"focal_ratio"].toDouble(), payload[
"id"].
toString());
1463void Message::processTrainCommands(
const QString &command,
const QJsonObject &payload)
1465 if (command == commands[TRAIN_GET_PROFILES])
1466 sendTrainProfiles();
1467 else if (command == commands[TRAIN_SET])
1469 auto module = payload["module"].toString();
1470 auto name = payload[
"name"].toString();
1472 if (module ==
"capture")
1474 if (m_Manager->captureModule())
1475 m_Manager->captureModule()->setOpticalTrain(name);
1477 else if (module ==
"focus")
1479 if (m_Manager->focusModule())
1480 m_Manager->focusModule()->mainFocuser()->setOpticalTrain(name);
1482 else if (module ==
"guide")
1484 if (m_Manager->guideModule())
1485 m_Manager->guideModule()->setOpticalTrain(name);
1487 else if (module ==
"align")
1489 if (m_Manager->alignModule())
1490 m_Manager->alignModule()->setOpticalTrain(name);
1492 else if (module ==
"mount")
1494 if (m_Manager->mountModule())
1495 m_Manager->mountModule()->setOpticalTrain(name);
1497 else if (module ==
"darklibrary")
1499 Ekos::DarkLibrary::Instance()->setOpticalTrain(name);
1502 else if (command == commands[TRAIN_ADD])
1504 Ekos::OpticalTrainManager::Instance()->addOpticalTrain(payload);
1506 else if (command == commands[TRAIN_UPDATE])
1508 Ekos::OpticalTrainManager::Instance()->setOpticalTrain(payload);
1510 else if (command == commands[TRAIN_DELETE])
1512 Ekos::OpticalTrainManager::Instance()->removeOpticalTrain(payload[
"name"].
toString());
1514 else if (command == commands[TRAIN_RESET])
1516 Ekos::OpticalTrainManager::Instance()->reset();
1518 else if (command == commands[TRAIN_ACCEPT])
1520 requestOpticalTrains(
false);
1521 Ekos::OpticalTrainManager::Instance()->accept();
1529void Message::processFilterManagerCommands(
const QString &command,
const QJsonObject &payload)
1532 if (m_Manager->captureModule())
1533 manager = m_Manager->captureModule()->mainCamera()->filterManager();
1538 if (command == commands[FM_GET_DATA])
1541 sendResponse(commands[FM_GET_DATA], data);
1543 else if (command == commands[FM_SET_DATA])
1545 manager->setFilterData(payload);
1552void Message::processDarkLibraryCommands(
const QString &command,
const QJsonObject &payload)
1554 if (command == commands[DARK_LIBRARY_START])
1555 Ekos::DarkLibrary::Instance()->start();
1556 else if(command == commands[DARK_LIBRARY_SET_ALL_SETTINGS])
1559 Ekos::DarkLibrary::Instance()->setAllSettings(settings);
1560 KSUtils::setGlobalSettings(settings);
1562 else if(command == commands[DARK_LIBRARY_GET_ALL_SETTINGS])
1563 sendDarkLibrarySettings(Ekos::DarkLibrary::Instance()->getAllSettings());
1564 else if(command == commands[DARK_LIBRARY_GET_DEFECT_SETTINGS])
1565 sendResponse(commands[DARK_LIBRARY_GET_DEFECT_SETTINGS], Ekos::DarkLibrary::Instance()->getDefectSettings());
1566 else if(command == commands[DARK_LIBRARY_SET_CAMERA_PRESETS])
1568 Ekos::DarkLibrary::Instance()->setCameraPresets(payload);
1570 else if (command == commands[DARK_LIBRARY_STOP])
1572 Ekos::DarkLibrary::Instance()->stop();
1574 else if (command == commands[DARK_LIBRARY_GET_MASTERS_IMAGE])
1576 const int row = payload[
"row"].toInt();
1577 Ekos::DarkLibrary::Instance()->loadIndexInView(row);
1579 else if (command == commands[DARK_LIBRARY_GET_CAMERA_PRESETS])
1581 sendResponse(commands[DARK_LIBRARY_GET_CAMERA_PRESETS], Ekos::DarkLibrary::Instance()->getCameraPresets());
1583 else if (command == commands[DARK_LIBRARY_SET_DEFECT_PIXELS])
1585 Ekos::DarkLibrary::Instance()->setDefectPixels(payload);
1587 else if (command == commands[DARK_LIBRARY_SAVE_MAP])
1589 Ekos::DarkLibrary::Instance()->saveMapB->click();
1591 else if (command == commands[DARK_LIBRARY_SET_DEFECT_FRAME])
1593 Ekos::DarkLibrary::Instance()->setDefectMapEnabled(
false);
1595 else if (command == commands[DARK_LIBRARY_GET_VIEW_MASTERS])
1597 sendResponse(commands[DARK_LIBRARY_GET_VIEW_MASTERS], Ekos::DarkLibrary::Instance()->getViewMasters());
1599 else if (command == commands[DARK_LIBRARY_CLEAR_MASTERS_ROW])
1601 const int rowIndex = payload[
"row"].toInt();
1602 Ekos::DarkLibrary::Instance()->clearRow(rowIndex);
1609void Message::processDeviceCommands(
const QString &command,
const QJsonObject &payload)
1611 QString device = payload[
"device"].toString();
1614 if (device.
isEmpty() && command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1616 m_PropertySubscriptions.clear();
1621 if (!INDIListener::findDevice(device, oneDevice))
1625 if (command == commands[DEVICE_PROPERTY_GET])
1628 if (oneDevice->getJSONProperty(payload[
"property"].toString(), propObject, payload[
"compact"].toBool(
true)))
1629 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
1632 else if (command == commands[DEVICE_PROPERTY_SET])
1634 oneDevice->setJSONProperty(payload[
"property"].
toString(), payload[
"elements"].toArray());
1637 else if (command == commands[DEVICE_GET])
1640 for (
const auto &oneProp : *oneDevice->getProperties())
1643 if (oneDevice->getJSONProperty(oneProp.getName(), singleProp, payload[
"compact"].toBool(
false)))
1653 sendResponse(commands[DEVICE_GET], response);
1657 else if (command == commands[DEVICE_PROPERTY_SUBSCRIBE])
1660 const QJsonArray groups = payload[
"groups"].toArray();
1664 if (m_PropertySubscriptions.contains(device))
1665 props = m_PropertySubscriptions[device];
1670 for (
const auto &oneProp : properties)
1671 props.
insert(oneProp.toString());
1674 else if (groups.
isEmpty() ==
false)
1677 for (
auto &oneProp : *oneDevice->getProperties())
1679 if (indiGroups.contains(oneProp.getGroupName()))
1680 props.
insert(oneProp.getName());
1686 for (
auto &oneProp : *oneDevice->getProperties())
1687 props.
insert(oneProp.getName());
1690 m_PropertySubscriptions[device] = props;
1692 else if (command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1695 const QJsonArray groups = payload[
"groups"].toArray();
1699 if (m_PropertySubscriptions.contains(device))
1700 props = m_PropertySubscriptions[device];
1706 for (
const auto &oneProp : properties)
1707 props.
remove(oneProp.toString());
1710 else if (groups.
isEmpty() ==
false)
1713 for (
auto &oneProp : *oneDevice->getProperties())
1715 if (indiGroups.contains(oneProp.getGroupName()))
1716 props.
remove(oneProp.getName());
1722 for (
auto &oneProp : *oneDevice->getProperties())
1723 props.
remove(oneProp.getName());
1726 m_PropertySubscriptions[device] = props;
1733void Message::processAstronomyCommands(
const QString &command,
const QJsonObject &payload)
1735 if (command == commands[ASTRO_GET_ALMANC])
1742 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
1746 {
"SunRise", almanac.getSunRise()},
1747 {
"SunSet", almanac.getSunSet()},
1748 {
"SunMaxAlt", almanac.getSunMaxAlt()},
1749 {
"SunMinAlt", almanac.getSunMinAlt()},
1750 {
"MoonRise", almanac.getMoonRise()},
1751 {
"MoonSet", almanac.getMoonSet()},
1752 {
"MoonPhase", almanac.getMoonPhase()},
1753 {
"MoonIllum", almanac.getMoonIllum()},
1754 {
"Dawn", almanac.getDawnAstronomicalTwilight()},
1755 {
"Dusk", almanac.getDuskAstronomicalTwilight()},
1759 sendResponse(commands[ASTRO_GET_ALMANC], response);
1761 else if (command == commands[ASTRO_GET_NAMES])
1763 auto composite = KStarsData::Instance()->skyComposite();
1766 CatalogsDB::CatalogObjectList dsoObjects;
1768 allObjects.
append(composite->objectLists(SkyObject::STAR));
1769 allObjects.
append(composite->objectLists(SkyObject::CATALOG_STAR));
1770 allObjects.
append(composite->objectLists(SkyObject::PLANET));
1771 allObjects.
append(composite->objectLists(SkyObject::MOON));
1772 allObjects.
append(composite->objectLists(SkyObject::COMET));
1773 allObjects.
append(composite->objectLists(SkyObject::ASTEROID));
1774 allObjects.
append(composite->objectLists(SkyObject::SUPERNOVA));
1775 allObjects.
append(composite->objectLists(SkyObject::SATELLITE));
1776 dsoObjects = m_DSOManager.get_objects_all();
1778 for (
auto &oneObject : allObjects)
1779 all << oneObject.second->name() << oneObject.second->longname().split(
", ");
1781 for (
auto &oneObject : dsoObjects)
1782 all << oneObject.name() << oneObject.longname().split(
", ");
1788 else if (command == commands[ASTRO_GET_DESIGNATIONS])
1792 for (
auto &oneObject : m_DSOManager.get_objects_all())
1796 {
"primary", oneObject.name()},
1800 designations.
append(oneDesignation);
1803 sendResponse(commands[ASTRO_GET_DESIGNATIONS], designations);
1805 else if (command == commands[ASTRO_GET_LOCATION])
1807 auto geo = KStarsData::Instance()->geo();
1810 {
"name",
geo->name()},
1811 {
"longitude",
geo->lng()->Degrees()},
1812 {
"latitude",
geo->lat()->Degrees()},
1813 {
"elevation",
geo->elevation()},
1818 sendResponse(commands[ASTRO_GET_LOCATION], location);
1821 else if (command == commands[ASTRO_SEARCH_OBJECTS])
1824 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
1827 KStarsData::Instance()->clock()->setManualMode(
false);
1828 KStarsData::Instance()->clock()->setUTC(jd);
1833 auto objectType =
static_cast<SkyObject::TYPE>(payload[
"type"].toInt(SkyObject::GALAXY));
1835 auto objectDirection =
static_cast<Direction
>(payload[
"direction"].toInt(All));
1837 auto objectMaxMagnitude = payload[
"maxMagnitude"].toDouble(10);
1839 auto objectMinAlt = payload[
"minAlt"].toDouble(15);
1841 auto objectMinDuration = payload[
"minDuration"].toInt(3600);
1843 auto objectMinFOV = payload[
"minFOV"].toDouble(0);
1845 auto *data = KStarsData::Instance();
1847 auto *
geo = KStarsData::Instance()->geo();
1850 auto start = KStarsData::Instance()->lt();
1851 auto end = getNextDawn();
1857 CatalogsDB::CatalogObjectList dsoObjects;
1863 case SkyObject::STAR:
1864 case SkyObject::CATALOG_STAR:
1865 allObjects.
append(data->skyComposite()->objectLists(SkyObject::STAR));
1866 allObjects.
append(data->skyComposite()->objectLists(SkyObject::CATALOG_STAR));
1869 case SkyObject::PLANET:
1870 case SkyObject::MOON:
1871 allObjects.
append(data->skyComposite()->objectLists(SkyObject::PLANET));
1872 allObjects.
append(data->skyComposite()->objectLists(SkyObject::MOON));
1875 case SkyObject::COMET:
1876 allObjects.
append(data->skyComposite()->objectLists(SkyObject::COMET));
1878 case SkyObject::ASTEROID:
1879 allObjects.
append(data->skyComposite()->objectLists(SkyObject::ASTEROID));
1882 case SkyObject::OPEN_CLUSTER:
1883 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::OPEN_CLUSTER, objectMaxMagnitude));
1886 case SkyObject::GLOBULAR_CLUSTER:
1887 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GLOBULAR_CLUSTER, objectMaxMagnitude));
1891 case SkyObject::GASEOUS_NEBULA:
1892 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GASEOUS_NEBULA, objectMaxMagnitude));
1895 case SkyObject::PLANETARY_NEBULA:
1896 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::PLANETARY_NEBULA, objectMaxMagnitude));
1899 case SkyObject::GALAXY:
1900 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GALAXY, objectMaxMagnitude));
1903 case SkyObject::SUPERNOVA:
1905 if (!Options::showSupernovae())
1907 Options::setShowSupernovae(
true);
1908 data->setFullTimeUpdate();
1911 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SUPERNOVA));
1914 case SkyObject::SATELLITE:
1916 if (!Options::showSatellites())
1918 Options::setShowSatellites(
true);
1919 data->setFullTimeUpdate();
1922 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SATELLITE));
1930 std::sort(allObjects.
begin(), allObjects.
end(), [](
const auto & a,
const auto & b)
1932 return a.second->mag() < b.second->mag();
1935 QMutableVectorIterator<QPair<QString, const SkyObject *>> objectIterator(allObjects);
1938 if (objectDirection != All)
1940 QPair<int, int> Quardent1(270, 360), Quardent2(0, 90), Quardent3(90, 180), Quardent4(180, 270);
1941 QPair<int, int> minAZ, maxAZ;
1942 switch (objectDirection)
1966 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1967 while (dsoIterator != dsoObjects.end())
1970 const double az = (*dsoIterator).recomputeHorizontalCoords(start, geo).az().Degrees();
1971 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1972 dsoIterator = dsoObjects.erase(dsoIterator);
1979 while (objectIterator.hasNext())
1981 const auto az = objectIterator.next().second->recomputeHorizontalCoords(start, geo).az().Degrees();
1982 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1983 objectIterator.remove();
1991 objectIterator.toFront();
1992 while (objectIterator.hasNext())
1994 auto magnitude = objectIterator.next().second->mag();
1996 if (magnitude != NaN::f && magnitude > objectMaxMagnitude)
1997 objectIterator.remove();
2004 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
2005 while (dsoIterator != dsoObjects.end())
2007 double duration = 0;
2010 dms LST =
geo->GSTtoLST(t.gst());
2011 (*dsoIterator).EquatorialToHorizontal(&LST,
geo->lat());
2012 if ((*dsoIterator).alt().Degrees() >= objectMinAlt)
2016 if (duration < objectMinDuration)
2017 dsoIterator = dsoObjects.erase(dsoIterator);
2024 objectIterator.toFront();
2025 while (objectIterator.hasNext())
2027 auto oneObject = objectIterator.next().second;
2028 double duration = 0;
2032 auto LST =
geo->GSTtoLST(t.gst());
2033 const_cast<SkyObject *
>(oneObject)->EquatorialToHorizontal(&LST,
geo->lat());
2034 if (oneObject->alt().Degrees() >= objectMinAlt)
2038 if (duration < objectMinDuration)
2039 objectIterator.remove();
2044 if (isDSO && objectMinFOV > 0)
2046 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
2047 while (dsoIterator != dsoObjects.end())
2049 if ((*dsoIterator).a() < objectMinFOV)
2050 dsoIterator = dsoObjects.erase(dsoIterator);
2057 for (
auto &oneObject : allObjects)
2058 searchObjects.
append(oneObject.second->name());
2059 for (
auto &oneObject : dsoObjects)
2060 searchObjects.
append(oneObject.name());
2065 sendResponse(commands[ASTRO_SEARCH_OBJECTS], response);
2067 else if(command == commands[ASTRO_GET_OBJECT_INFO])
2069 const auto name = payload[
"object"].toString();
2070 bool exact = payload[
"exact"].toBool(
false);
2072 SkyObject *oneObject = KStarsData::Instance()->skyComposite()->findByName(name, exact);
2077 {
"name", exact ?
name : oneObject->
name()},
2079 {
"magnitude", oneObject->
mag()},
2082 {
"ra", oneObject->
ra().
Hours()},
2086 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info);
2095 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info );
2100 else if (command == commands[ASTRO_GET_OBJECTS_INFO])
2103 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2106 KStarsData::Instance()->clock()->setManualMode(
false);
2107 KStarsData::Instance()->clock()->setUTC(jd);
2111 bool exact = payload[
"exact"].toBool(
false);
2112 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2115 for (
auto &oneName : objectNames)
2118 SkyObject *oneObject = KStarsData::Instance()->skyComposite()->findByName(name, exact);
2123 {
"name", exact ?
name : oneObject->
name()},
2125 {
"magnitude", oneObject->
mag()},
2128 {
"ra", oneObject->
ra().
Hours()},
2136 info[
"a"] = dsoObject->
a();
2137 info[
"b"] = dsoObject->
b();
2138 info[
"pa"] = dsoObject->
pa();
2141 objectsArray.
append(info);
2145 sendResponse(commands[ASTRO_GET_OBJECTS_INFO], objectsArray);
2148 else if (command == commands[ASTRO_GET_OBJECTS_OBSERVABILITY])
2151 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2154 KStarsData::Instance()->clock()->setManualMode(
false);
2155 KStarsData::Instance()->clock()->setUTC(jd);
2159 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2162 bool exact = payload[
"exact"].toBool(
false);
2164 auto *data = KStarsData::Instance();
2166 auto *
geo = KStarsData::Instance()->geo();
2168 auto ut = data->ut();
2170 for (
auto &oneName : objectNames)
2173 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2177 dms ha(data->lst()->Degrees() - oneObject->
ra().
Degrees());
2180 {
"name", exact ?
name : oneObject->
name()},
2186 objectsArray.
append(info);
2190 sendResponse(commands[ASTRO_GET_OBJECTS_OBSERVABILITY], objectsArray);
2192 else if (command == commands[ASTRO_GET_OBJECTS_RISESET])
2195 if (payload.
contains(
"jd") && m_Manager && m_Manager->getEkosStartingStatus() == Ekos::Idle)
2198 KStarsData::Instance()->clock()->setManualMode(
false);
2199 KStarsData::Instance()->clock()->setUTC(jd);
2203 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2206 bool exact = payload[
"exact"].toBool(
false);
2208 auto *data = KStarsData::Instance();
2210 auto *
geo = KStarsData::Instance()->geo();
2216 if (data->lt().time().hour() > 12)
2219 for (
auto &oneName : objectNames)
2222 SkyObject *oneObject = data->skyComposite()->findByName(name, exact);
2232 if (transitTime < riseTime)
2239 if (setTime < riseTime)
2242 info[
"name"] = exact ?
name : oneObject->
name();
2252 info[
"rise"] =
"Circumpolar";
2253 info[
"set"] =
"Circumpolar";
2257 info[
"rise"] =
"Never rises";
2258 info[
"set"] =
"Never rises";
2265 for (
double h = -12.0; h <= 12.0; h += 0.5)
2267 double hour = h + (24.0 * DayOffset);
2274 info[
"altitudes"] = altitudes;
2276 objectsArray.
append(info);
2280 sendResponse(commands[ASTRO_GET_OBJECTS_RISESET], objectsArray);
2289 if (command == commands[FILE_DEFAULT_PATH])
2291 sendResponse(commands[FILE_DEFAULT_PATH],
2294 else if (command == commands[FILE_DIRECTORY_OPERATION])
2296 auto path = payload[
"path"].toString();
2297 auto operation = payload[
"operation"].toString();
2299 if (operation ==
"create")
2304 {
"operation", operation}
2307 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2309 else if (operation ==
"remove")
2314 {
"operation", operation}
2317 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2319 else if (operation ==
"list")
2321 auto namedFilters = payload[
"namedFilters"].toString(
"*").split(
",");
2326 for (
auto &oneEntry : list)
2330 {
"name", oneEntry.fileName()},
2331 {
"path", oneEntry.absolutePath()},
2332 {
"size", oneEntry.size()},
2333 {
"isFile", oneEntry.isFile()},
2334 {
"creation", oneEntry.birthTime().toSecsSinceEpoch()},
2335 {
"modified", oneEntry.lastModified().toSecsSinceEpoch()}
2338 entries.push_back(info);
2343 {
"result", !entries.empty()},
2344 {
"operation", operation},
2345 {
"payload", entries}
2348 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2350 else if (operation ==
"exists")
2355 {
"operation", operation}
2358 sendResponse(commands[FILE_DIRECTORY_OPERATION], info);
2373 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
2377 if (nextDawn < localTime)
2386void Message::requestDSLRInfo(
const QString &cameraName)
2388 sendResponse(commands[DSLR_GET_INFO], cameraName);
2394void Message::requestPortSelection(
bool show)
2396 sendResponse(commands[GET_PROFILE_PORT_SELECTION], show);
2402void Message::sendDialog(
const QJsonObject &message)
2404 sendResponse(commands[DIALOG_GET_INFO], message);
2412 for (
auto &nodeManager : m_NodeManagers)
2414 nodeManager->message()->sendResponse(command, payload);
2423 for (
auto &nodeManager : m_NodeManagers)
2425 nodeManager->message()->sendResponse(command, payload);
2432void Message::sendResponse(
const QString &command,
const QString &payload)
2434 for (
auto &nodeManager : m_NodeManagers)
2436 nodeManager->message()->sendResponse(command, payload);
2443void Message::sendResponse(
const QString &command,
bool payload)
2445 for (
auto &nodeManager : m_NodeManagers)
2447 nodeManager->message()->sendResponse(command, payload);
2454void Message::autofocusAborted()
2458 {
"status",
"Aborted"}
2460 sendResponse(commands[NEW_FOCUS_STATE], cStatus);
2466void Message::updateMountStatus(
const QJsonObject &status,
bool throttle)
2471 if (m_ThrottleTS.msecsTo(now) >= THROTTLE_INTERVAL)
2474 sendResponse(commands[NEW_MOUNT_STATE], status);
2478 sendResponse(commands[NEW_MOUNT_STATE], status);
2484void Message::updateCaptureStatus(
const QJsonObject &status)
2486 sendResponse(commands[NEW_CAPTURE_STATE], status);
2492void Message::updateFocusStatus(
const QJsonObject &status)
2494 sendResponse(commands[NEW_FOCUS_STATE], status);
2500void Message::updateGuideStatus(
const QJsonObject &status)
2502 sendResponse(commands[NEW_GUIDE_STATE], status);
2508void Message::updateDomeStatus(
const QJsonObject &status)
2510 sendResponse(commands[NEW_DOME_STATE], status);
2516void Message::updateCapStatus(
const QJsonObject &status)
2518 sendResponse(commands[NEW_CAP_STATE], status);
2524void Message::updateAlignStatus(
const QJsonObject &status)
2526 sendResponse(commands[NEW_ALIGN_STATE], status);
2532void Message::sendConnection()
2536 {
"connected",
true},
2537 {
"online", m_Manager->getEkosStartingStatus() == Ekos::Success}
2540 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
2546void Message::sendStates()
2549 if (m_Manager->captureModule())
2551 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2552 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2553 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2556 if (m_Manager->mountModule())
2560 {
"status", m_Manager->mountModule()->statusString(
false)},
2561 {
"target", m_Manager->capturePreview->mountTarget->text()},
2562 {
"slewRate", m_Manager->mountModule()->slewRate()},
2563 {
"pierSide", m_Manager->mountModule()->pierSide()}
2566 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2569 if (m_Manager->focusModule())
2571 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2572 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2575 if (m_Manager->guideModule())
2577 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2578 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2581 if (m_Manager->alignModule())
2586 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2588 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2591 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2598 doc.
setHtml(paa->getPAHMessage());
2601 {
"stage", paa->getPAHStageString(
false)},
2605 sendResponse(commands[NEW_POLAR_STATE], polarState);
2613void Message::sendEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
2615 if (Options::ekosLiveNotifications() ==
false)
2621 {
"severity",
event},
2622 {
"message", message},
2626 sendResponse(commands[NEW_NOTIFICATION], newEvent);
2632void Message::sendManualRotatorStatus(
double currentPA,
double targetPA,
double threshold)
2634 QJsonObject request = {{
"currentPA", currentPA}, {
"targetPA", targetPA}, {
"threshold", threshold}};
2635 sendResponse(commands[ALIGN_MANUAL_ROTATOR_STATUS], request);
2641void Message::setBoundingRect(
QRect rect,
QSize view,
double currentZoom)
2643 m_BoundingRect = rect;
2645 m_CurrentZoom = currentZoom;
2651void Message::processDialogResponse(
const QJsonObject &payload)
2653 KSMessageBox::Instance()->selectResponse(payload[
"button"].
toString());
2659void Message::processNewProperty(INDI::Property prop)
2664 if (m_Manager->settleStatus() != Ekos::CommunicationStatus::Success)
2668 ISD::propertyToJson(prop, propObject,
false);
2669 sendResponse(commands[DEVICE_PROPERTY_ADD], propObject);
2675void Message::processDeleteProperty(INDI::Property prop)
2679 {
"device", prop.getDeviceName()},
2680 {
"name", prop.getName()}
2683 sendResponse(commands[DEVICE_PROPERTY_REMOVE], payload);
2691 if (Options::ekosLiveNotifications() ==
false)
2697 {
"device", device->getDeviceName()},
2698 {
"message", message}
2701 sendResponse(commands[DEVICE_MESSAGE], payload);
2707void Message::processUpdateProperty(INDI::Property prop)
2709 if (m_PropertySubscriptions.contains(prop.getDeviceName()))
2711 QSet<QString> subProps = m_PropertySubscriptions[prop.getDeviceName()];
2712 if (subProps.
contains(prop.getName()))
2714 PendingProperty pending{prop.getDeviceName(), prop.getName()};
2715 m_PendingProperties.remove(pending);
2716 m_PendingProperties.insert(pending);
2724void Message::setPendingPropertiesEnabled(
bool enabled)
2727 m_PendingPropertiesTimer.start();
2730 m_PendingProperties.clear();
2732 if (m_PendingPropertiesTimer.isActive())
2734 m_PendingPropertiesTimer.stop();
2735 std::this_thread::sleep_for(std::chrono::milliseconds(500));
2743void Message::sendPendingProperties()
2749 for (
const auto &pending : m_PendingProperties)
2750 deviceProperties[pending.device].
insert(pending.name);
2753 for (
auto it = deviceProperties.
constBegin(); it != deviceProperties.
constEnd(); ++it)
2757 if (INDIListener::findDevice(it.key(), device))
2760 for (
const auto &propName : it.value())
2762 auto prop = device->getProperty(propName);
2766 ISD::propertyToJson(prop, propObject);
2767 sendResponse(commands[DEVICE_PROPERTY_GET], propObject);
2774 m_PendingProperties.clear();
2780void Message::sendModuleState(
const QString &name)
2782 if (name ==
"Capture")
2784 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2785 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2786 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2788 else if (name ==
"Mount")
2792 {
"status", m_Manager->mountStatus->getStatusText()},
2793 {
"target", m_Manager->capturePreview->mountTarget->text()},
2794 {
"slewRate", m_Manager->mountModule()->slewRate()},
2795 {
"pierSide", m_Manager->mountModule()->pierSide()}
2798 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2800 else if (name ==
"Focus")
2802 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->mainFocuser()->status(),
false)}};
2803 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2805 else if (name ==
"Guide")
2807 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2808 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2810 else if (name ==
"Align")
2815 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2817 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2820 sendAlignSettings(m_Manager->alignModule()->getAllSettings());
2827 doc.
setHtml(paa->getPAHMessage());
2830 {
"stage", paa->getPAHStageString(
false)},
2834 sendResponse(commands[NEW_POLAR_STATE], polarState);
2846 if (name ==
"Manager")
2860 for (
auto &tab : viewer->tabs())
2862 if (tab->getView()->objectName() == name)
2863 return tab->getView().get();
2876#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2877bool Message::parseArgument(
QVariant::Type type,
const QVariant &arg, QMetaMethodArgument &genericArg, SimpleTypes &types)
2886 case QVariant::Type::Int:
2887 types.number_integer = arg.
toInt();
2888 genericArg = Q_ARG(
int, types.number_integer);
2890 case QVariant::Type::UInt:
2891 types.number_unsigned_integer = arg.
toUInt();
2892 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2894 case QVariant::Type::LongLong:
2896 genericArg = Q_ARG(
int, types.number_integer);
2898 case QVariant::Type::ULongLong:
2899 types.number_unsigned_integer = arg.
toULongLong();
2900 genericArg = Q_ARG(uint, types.number_unsigned_integer);
2902 case QVariant::Type::Double:
2903 types.number_double = arg.
toDouble();
2904 genericArg = Q_ARG(
double, types.number_double);
2906 case QVariant::Type::Bool:
2907 types.boolean = arg.
toBool();
2908 genericArg = Q_ARG(
bool, types.boolean);
2910 case QVariant::Type::String:
2912 genericArg = Q_ARG(
QString, types.text);
2914 case QVariant::Type::Url:
2915 types.url = arg.
toUrl();
2916 genericArg = Q_ARG(
QUrl, types.
url);
2930#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2938 auto name = payload[
"name"].toString().toLatin1();
2944 for (
auto oneArg : args)
2946 auto argObject = oneArg.toObject();
2947#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
2948 QMetaMethodArgument genericArgument;
2952 SimpleTypes genericType;
2953 argsList.
append(genericArgument);
2954 typesList.
append(genericType);
2955 if (parseArgument(
static_cast<QVariant::Type>(argObject[
"type"].toInt()), argObject[
"value"].toVariant(), argsList.
back(),
2956 typesList.
last()) ==
false)
2963 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.
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,...
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,...
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 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.
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
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator insert(const Key &key, const T &value)
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