12 #include "profileinfo.h"
13 #include "indi/drivermanager.h"
14 #include "auxiliary/ksmessagebox.h"
16 #include "kstarsdata.h"
17 #include "ekos_debug.h"
18 #include "fitsviewer/fitsview.h"
19 #include "ksalmanac.h"
20 #include "skymapcomposite.h"
21 #include "catalogobject.h"
22 #include "ekos/auxiliary/darklibrary.h"
26 #include <KActionCollection>
27 #include <basedevice.h>
32 Message::Message(Ekos::Manager *manager): m_Manager(manager), m_DSOManager(CatalogsDB::dso_db_path())
39 connect(manager, &Ekos::Manager::newModule,
this, &Message::sendModuleState);
44 void Message::connectServer()
46 QUrl requestURL(m_URL);
49 query.addQueryItem(
"username", m_AuthResponse[
"username"].
toString());
50 query.addQueryItem(
"token", m_AuthResponse[
"token"].
toString());
51 if (m_AuthResponse.contains(
"remoteToken"))
52 query.addQueryItem(
"remoteToken", m_AuthResponse[
"remoteToken"].
toString());
53 query.addQueryItem(
"email", m_AuthResponse[
"email"].
toString());
54 query.addQueryItem(
"from_date", m_AuthResponse[
"from_date"].
toString());
55 query.addQueryItem(
"to_date", m_AuthResponse[
"to_date"].
toString());
56 query.addQueryItem(
"plan_id", m_AuthResponse[
"plan_id"].
toString());
57 query.addQueryItem(
"type", m_AuthResponse[
"type"].
toString());
59 requestURL.setPath(
"/message/ekos");
60 requestURL.setQuery(query);
63 m_WebSocket.open(requestURL);
65 qCInfo(KSTARS_EKOS) <<
"Connecting to Websocket server at" << requestURL.toDisplayString();
68 void Message::disconnectServer()
73 void Message::onConnected()
75 qCInfo(KSTARS_EKOS) <<
"Connected to Message Websocket server at" << m_URL.toDisplayString();
88 void Message::onDisconnected()
90 qCInfo(KSTARS_EKOS) <<
"Disconnected from Message Websocket server.";
91 m_isConnected =
false;
93 m_PropertyCache.clear();
100 qCritical(KSTARS_EKOS) <<
"Websocket connection error" << m_WebSocket.errorString();
104 if (m_ReconnectTries++ < RECONNECT_MAX_TRIES)
112 qCInfo(KSTARS_EKOS) <<
"Websocket Message" <<
message;
117 qCWarning(KSTARS_EKOS) <<
"Ekos Live Parsing Error" <<
error.errorString();
131 const QString command = msgObj[
"type"].toString();
132 const QJsonObject payload = msgObj[
"payload"].toObject();
134 if (command == commands[GET_CONNECTION])
138 else if (command == commands[LOGOUT])
143 else if (command == commands[SET_CLIENT_STATE])
146 if (payload[
"state"].toBool(
false))
148 qCInfo(KSTARS_EKOS) <<
"EkosLive client is connected.";
151 if (KStarsData::Instance()->clock()->isActive() ==
false)
153 qCInfo(KSTARS_EKOS) <<
"Resuming and syncing clock.";
164 qCInfo(KSTARS_EKOS) <<
"EkosLive client is disconnected.";
166 if (
KStars::Instance()->isStartedWithClockRunning() ==
false && m_Manager->ekosStatus() == Ekos::CommunicationStatus::Idle)
168 qCInfo(KSTARS_EKOS) <<
"Stopping the clock.";
173 else if (command == commands[GET_DRIVERS])
175 else if (command == commands[GET_PROFILES])
177 else if (command == commands[GET_SCOPES])
180 processScopeCommands(command, payload);
182 processProfileCommands(command, payload);
184 processAstronomyCommands(command, payload);
185 else if (command == commands[DIALOG_GET_RESPONSE])
186 processDialogResponse(payload);
188 processOptionsCommands(command, payload);
190 processSchedulerCommands(command, payload);
192 if (m_Manager->getEkosStartingStatus() != Ekos::Success)
195 if (command == commands[GET_STATES])
197 else if (command == commands[GET_CAMERAS])
201 if (m_Manager->captureModule())
202 m_Manager->captureModule()->checkCamera();
204 else if (command == commands[GET_MOUNTS])
206 else if (command == commands[GET_FILTER_WHEELS])
208 else if (command == commands[GET_DOMES])
210 else if (command == commands[GET_CAPS])
212 else if (command == commands[GET_STELLARSOLVER_PROFILES])
213 sendStellarSolverProfiles();
214 else if (command == commands[GET_DEVICES])
217 processCaptureCommands(command, payload);
219 processMountCommands(command, payload);
221 processFocusCommands(command, payload);
223 processGuideCommands(command, payload);
225 processAlignCommands(command, payload);
227 processPolarCommands(command, payload);
229 processDSLRCommands(command, payload);
231 processFilterManagerCommands(command, payload);
233 processDarkLibraryCommands(command, payload);
235 processDeviceCommands(command, payload);
239 void Message::sendCameras()
241 if (m_isConnected ==
false)
246 for(
auto &oneDevice : m_Manager->getAllDevices())
248 auto camera =
dynamic_cast<ISD::Camera*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::CCD_INTERFACE));
252 auto primaryChip = camera->getChip(ISD::CameraChip::PRIMARY_CCD);
254 double temperature = Ekos::INVALID_VALUE;
255 camera->getTemperature(&temperature);
259 {
"name", camera->getDeviceName()},
260 {
"canBin", primaryChip->canBin()},
261 {
"hasTemperature", camera->hasCooler()},
262 {
"canCool", camera->canCool()},
264 {
"hasVideo", camera->hasVideoStream()},
265 {
"hasGain", camera->hasGain()}
268 cameraList.
append(oneCamera);
271 sendResponse(commands[GET_CAMERAS], cameraList);
274 for(
auto &oneDevice : m_Manager->getAllDevices())
276 auto camera =
dynamic_cast<ISD::Camera*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::CCD_INTERFACE));
280 QJsonObject state = {{
"name", camera->getDeviceName()}};
283 if (camera->canCool())
285 camera->getTemperature(&value);
286 state[
"temperature"] = value;
288 if (camera->hasGain())
290 camera->getGain(&value);
291 state[
"gain"] = value;
293 if (camera->getChip(ISD::CameraChip::PRIMARY_CCD)->getISOIndex() >= 0)
295 state[
"iso"] = camera->getChip(ISD::CameraChip::PRIMARY_CCD)->getISOIndex();
298 sendResponse(commands[NEW_CAMERA_STATE], state);
301 if (m_Manager->captureModule())
302 sendCaptureSettings(m_Manager->captureModule()->getPresetSettings());
303 if (m_Manager->alignModule())
304 sendAlignSettings(m_Manager->alignModule()->getSettings());
305 if (m_Manager->focusModule())
307 sendResponse(commands[FOCUS_SET_SETTINGS], m_Manager->focusModule()->getSettings());
308 sendResponse(commands[FOCUS_SET_PRIMARY_SETTINGS], m_Manager->focusModule()->getPrimarySettings());
309 sendResponse(commands[FOCUS_SET_PROCESS_SETTINGS], m_Manager->focusModule()->getProcessSettings());
310 sendResponse(commands[FOCUS_SET_MECHANICS_SETTINGS], m_Manager->focusModule()->getMechanicsSettings());
312 if (m_Manager->guideModule())
313 sendGuideSettings(m_Manager->guideModule()->getSettings());
316 void Message::sendMounts()
318 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
323 for(
auto &oneDevice : m_Manager->getAllDevices())
325 auto mount =
dynamic_cast<ISD::Mount*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::TELESCOPE_INTERFACE));
331 {
"name",
mount->getDeviceName()},
332 {
"canPark",
mount->canPark()},
333 {
"canSync",
mount->canSync()},
334 {
"canControlTrack",
mount->canControlTrack()},
335 {
"hasSlewRates",
mount->hasSlewRates()},
339 mountList.
append(oneMount);
342 sendResponse(commands[GET_MOUNTS], mountList);
345 for(
auto &oneDevice : m_Manager->getAllDevices())
347 auto mount =
dynamic_cast<ISD::Mount*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::TELESCOPE_INTERFACE));
353 {
"name",
mount->getDeviceName() },
354 {
"slewRate",
mount->getSlewRate() },
355 {
"pierSide",
mount->pierSide() },
358 sendResponse(commands[NEW_MOUNT_STATE], slewRate);
361 if (m_Manager->mountModule())
366 {
"altitudeLimitsEnabled", m_Manager->mountModule()->altitudeLimitsEnabled()},
367 {
"altitudeLimitsMin", m_Manager->mountModule()->altitudeLimits()[0]},
368 {
"altitudeLimitsMax", m_Manager->mountModule()->altitudeLimits()[1]},
369 {
"haLimitEnabled", m_Manager->mountModule()->hourAngleLimitEnabled()},
370 {
"haLimitValue", m_Manager->mountModule()->hourAngleLimit()},
371 {
"meridianFlipEnabled", m_Manager->mountModule()->meridianFlipEnabled()},
372 {
"meridianFlipValue", m_Manager->mountModule()->meridianFlipValue()},
373 {
"autoParkEnabled", m_Manager->mountModule()->autoParkEnabled()},
376 sendResponse(commands[MOUNT_GET_SETTINGS], mountModuleSettings);
380 void Message::sendDomes()
382 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
387 for(
auto &oneDevice : m_Manager->getAllDevices())
389 auto dome =
dynamic_cast<ISD::Dome*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::DOME_INTERFACE));
395 {
"name", dome->getDeviceName()},
396 {
"canPark", dome->canPark()},
397 {
"canGoto", dome->canAbsMove()},
398 {
"canAbort", dome->canAbort()},
404 sendResponse(commands[GET_DOMES], domeList);
407 for(
auto &oneDevice : m_Manager->getAllDevices())
409 auto dome =
dynamic_cast<ISD::Dome*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::DOME_INTERFACE));
415 {
"name", dome->getDeviceName()},
416 {
"status", ISD::Dome::getStatusString(dome->status())}
419 if (dome->canAbsMove())
420 status[
"az"] = dome->azimuthPosition();
422 sendResponse(commands[NEW_DOME_STATE], status);
427 void Message::sendCaps()
429 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
434 for(
auto &oneDevice : m_Manager->getAllDevices())
436 auto dustcap =
dynamic_cast<ISD::DustCap*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::DUSTCAP_INTERFACE));
442 {
"name", dustcap->getDeviceName()},
443 {
"canPark", dustcap->canPark()},
444 {
"hasLight", dustcap->hasLight()},
450 sendResponse(commands[GET_CAPS], capList);
452 for(
auto &oneDevice : m_Manager->getAllDevices())
454 auto dustcap =
dynamic_cast<ISD::DustCap*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::DUSTCAP_INTERFACE));
460 {
"name", dustcap->getDeviceName()},
461 {
"status", ISD::DustCap::getStatusString(dustcap->status())},
462 {
"lightS", dustcap->isLightOn()}
465 updateCapStatus(status);
470 void Message::sendStellarSolverProfiles()
472 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
477 if (m_Manager->focusModule())
482 if (m_Manager->alignModule())
486 sendResponse(commands[GET_STELLARSOLVER_PROFILES], profiles);
489 void Message::sendDrivers()
491 if (m_isConnected ==
false)
494 sendResponse(commands[GET_DRIVERS], DriverManager::Instance()->getDriverList());
497 void Message::sendDevices()
499 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
504 for(
auto &gd : m_Manager->getAllDevices())
508 {
"name", gd->getDeviceName()},
509 {
"connected", gd->isConnected()},
510 {
"version", gd->getDriverVersion()},
511 {
"interface",
static_cast<int>(gd->getDriverInterface())},
514 deviceList.
append(oneDevice);
517 sendResponse(commands[GET_DEVICES], deviceList);
520 void Message::sendScopes()
522 if (m_isConnected ==
false)
530 for (
auto &scope : allScopes)
531 scopeList.
append(scope->toJson());
533 sendResponse(commands[GET_SCOPES], scopeList);
536 void Message::sendTemperature(
double value)
544 {
"name", oneCCD->getDeviceName()},
545 {
"temperature", value}
548 sendResponse(commands[NEW_CAMERA_STATE], temperature);
552 void Message::sendFilterWheels()
554 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
559 for(
auto &oneDevice : m_Manager->getAllDevices())
561 auto filterwheel =
dynamic_cast<ISD::FilterWheel*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::FILTER_INTERFACE));
565 auto prop = filterwheel->getProperty(
"FILTER_NAME");
569 auto filterNames = prop->getText();
574 for (
const auto &it : *filterNames)
575 filters.
append(it.getText());
579 {
"name", filterwheel->getDeviceName()},
583 filterList.
append(oneFilter);
586 sendResponse(commands[GET_FILTER_WHEELS], filterList);
589 void Message::setCapturePresetSettings(
const QJsonObject &settings)
591 m_Manager->captureModule()->setPresetSettings(settings);
594 void Message::processCaptureCommands(
const QString &command,
const QJsonObject &payload)
598 if (capture ==
nullptr)
600 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as capture module is not available";
604 if (command == commands[CAPTURE_PREVIEW])
606 setCapturePresetSettings(payload);
609 else if (command == commands[CAPTURE_TOGGLE_CAMERA])
614 else if (command == commands[CAPTURE_TOGGLE_FILTER_WHEEL])
619 else if (command == commands[CAPTURE_TOGGLE_VIDEO])
621 capture->
setVideoLimits(payload[
"maxBufferSize"].toInt(512), payload[
"maxPreviewFPS"].toInt(10));
624 else if (command == commands[CAPTURE_START])
626 else if (command == commands[CAPTURE_STOP])
628 else if (command == commands[CAPTURE_LOOP])
630 setCapturePresetSettings(payload);
633 else if (command == commands[CAPTURE_GET_SEQUENCES])
637 else if (command == commands[CAPTURE_ADD_SEQUENCE])
640 setCapturePresetSettings(payload[
"preset"].toObject());
643 capture->
setCount(
static_cast<uint16_t
>(payload[
"count"].toInt()));
644 capture->
setDelay(
static_cast<uint16_t
>(payload[
"delay"].toInt()));
647 m_Manager->captureModule()->setFileSettings(payload[
"file"].toObject());
650 m_Manager->captureModule()->setCalibrationSettings(payload[
"calibration"].toObject());
655 else if (command == commands[CAPTURE_REMOVE_SEQUENCE])
657 if (capture->
removeJob(payload[
"index"].toInt()) ==
false)
660 else if (command == commands[CAPTURE_CLEAR_SEQUENCES])
664 else if (command == commands[CAPTURE_SET_LIMITS])
668 else if (command == commands[CAPTURE_GET_LIMITS])
672 else if (command == commands[CAPTURE_SAVE_SEQUENCE_FILE])
676 else if (command == commands[CAPTURE_LOAD_SEQUENCE_FILE])
680 else if (command == commands[CAPTURE_GET_CALIBRATION_SETTINGS])
684 else if (command == commands[CAPTURE_GET_FILE_SETTINGS])
686 sendResponse(commands[CAPTURE_GET_FILE_SETTINGS], capture->
getFileSettings());
688 else if (command == commands[CAPTURE_GENERATE_DARK_FLATS])
694 void Message::sendCaptureSequence(
const QJsonArray &sequenceArray)
696 sendResponse(commands[CAPTURE_GET_SEQUENCES], sequenceArray);
699 void Message::sendCaptureSettings(
const QJsonObject &settings)
701 sendResponse(commands[CAPTURE_SET_SETTINGS], settings);
704 void Message::sendAlignSettings(
const QJsonObject &settings)
706 sendResponse(commands[ALIGN_SET_SETTINGS], settings);
709 void Message::sendGuideSettings(
const QJsonObject &settings)
711 sendResponse(commands[GUIDE_SET_SETTINGS], settings);
714 void Message::sendFocusSettings(
const QJsonObject &settings)
716 sendResponse(commands[FOCUS_SET_SETTINGS], settings);
719 void Message::sendSchedulerSettings(
const QJsonObject &settings)
721 sendResponse(commands[SCHEDULER_GET_SETTINGS], settings);
724 void Message::processGuideCommands(
const QString &command,
const QJsonObject &payload)
728 if (guide ==
nullptr)
730 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as guide module is not available";
734 if (command == commands[GUIDE_START])
738 else if (command == commands[GUIDE_CAPTURE])
740 else if (command == commands[GUIDE_LOOP])
742 else if (command == commands[GUIDE_STOP])
744 else if (command == commands[GUIDE_CLEAR])
746 else if (command == commands[GUIDE_SET_SETTINGS])
748 guide->setSettings(payload);
749 sendGuideSettings(m_Manager->guideModule()->getSettings());
753 void Message::processFocusCommands(
const QString &command,
const QJsonObject &payload)
757 if (focus ==
nullptr)
759 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as focus module is not available";
763 if (command == commands[FOCUS_START])
765 else if (command == commands[FOCUS_CAPTURE])
770 else if (command == commands[FOCUS_STOP])
772 else if (command == commands[FOCUS_RESET])
774 else if (command == commands[FOCUS_IN])
775 focus->
focusIn(payload[
"steps"].toInt());
776 else if (command == commands[FOCUS_OUT])
777 focus->
focusOut(payload[
"steps"].toInt());
778 else if (command == commands[FOCUS_LOOP])
780 else if (command == commands[FOCUS_SET_SETTINGS])
781 focus->setSettings(payload);
782 else if (command == commands[FOCUS_SET_CROSSHAIR])
784 double x = payload[
"x"].toDouble();
785 double y = payload[
"y"].toDouble();
788 else if (command == commands[FOCUS_SET_PRIMARY_SETTINGS])
789 focus->setPrimarySettings(payload);
790 else if (command == commands[FOCUS_SET_PROCESS_SETTINGS])
791 focus->setProcessSettings(payload);
792 else if (command == commands[FOCUS_SET_MECHANICS_SETTINGS])
793 focus->setMechanicsSettings(payload);
794 else if (command == commands[FOCUS_GET_PRIMARY_SETTINGS])
795 sendResponse(commands[FOCUS_GET_PRIMARY_SETTINGS], focus->getPrimarySettings());
796 else if (command == commands[FOCUS_GET_PROCESS_SETTINGS])
797 sendResponse(commands[FOCUS_GET_PROCESS_SETTINGS], focus->getProcessSettings());
798 else if (command == commands[FOCUS_GET_MECHANICS_SETTINGS])
799 sendResponse(commands[FOCUS_GET_MECHANICS_SETTINGS], focus->getMechanicsSettings());
802 void Message::processMountCommands(
const QString &command,
const QJsonObject &payload)
806 if (mount ==
nullptr)
808 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as mount module is not available";
812 if (command == commands[MOUNT_ABORT])
814 else if (command == commands[MOUNT_PARK])
816 else if (command == commands[MOUNT_UNPARK])
818 else if (command == commands[MOUNT_SET_TRACKING])
819 mount->setTrackEnabled(payload[
"enabled"].toBool());
820 else if (command == commands[MOUNT_SYNC_RADE])
822 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
825 else if (command == commands[MOUNT_SYNC_TARGET])
829 else if (command == commands[MOUNT_GOTO_RADE])
831 mount->setJ2000Enabled(payload[
"isJ2000"].toBool());
834 else if (command == commands[MOUNT_GOTO_TARGET])
838 else if (command == commands[MOUNT_SET_SLEW_RATE])
840 int rate = payload[
"rate"].toInt(-1);
842 mount->setSlewRate(rate);
844 else if (command == commands[MOUNT_SET_MOTION])
846 QString direction = payload[
"direction"].toString();
847 ISD::Mount::MotionCommand action = payload[
"action"].toBool(
false) ?
848 ISD::Mount::MOTION_START : ISD::Mount::MOTION_STOP;
850 if (direction ==
"N")
851 mount->motionCommand(action, ISD::Mount::MOTION_NORTH, -1);
852 else if (direction ==
"S")
853 mount->motionCommand(action, ISD::Mount::MOTION_SOUTH, -1);
854 else if (direction ==
"E")
855 mount->motionCommand(action, -1, ISD::Mount::MOTION_EAST);
856 else if (direction ==
"W")
857 mount->motionCommand(action, -1, ISD::Mount::MOTION_WEST);
859 else if (command == commands[MOUNT_SET_ALTITUDE_LIMITS])
862 limits.
append(payload[
"min"].toDouble(0));
863 limits.
append(payload[
"max"].toDouble(90));
864 mount->setAltitudeLimits(limits);
865 mount->setAltitudeLimitsEnabled(payload[
"enabled"].toBool());
867 else if (command == commands[MOUNT_SET_HA_LIMIT])
869 mount->setHourAngleLimit(payload[
"value"].toDouble());
870 mount->setHourAngleLimitEnabled(payload[
"enabled"].toBool());
872 else if (command == commands[MOUNT_SET_MERIDIAN_FLIP])
875 mount->setMeridianFlipValues(payload[
"enabled"].toBool(),
876 payload[
"value"].toDouble() / 15.0);
878 else if (command == commands[MOUNT_SET_EVERYDAY_AUTO_PARK])
880 const bool enabled = payload[
"enabled"].toBool();
881 mount->setAutoParkDailyEnabled(enabled);
883 else if (command == commands[MOUNT_SET_AUTO_PARK])
885 const bool enabled = payload[
"enabled"].toBool();
889 mount->setAutoParkEnabled(enabled);
891 else if (command == commands[MOUNT_GOTO_PIXEL])
893 const auto name = payload[
"camera"].toString();
894 const auto xFactor = payload[
"x"].toDouble();
895 const auto yFactor = payload[
"y"].toDouble();
897 for(
auto &oneDevice : m_Manager->getAllDevices())
899 auto camera =
dynamic_cast<ISD::Camera*
>(oneDevice->getConcreteDevice(INDI::BaseDevice::CCD_INTERFACE));
900 if (!camera || camera->getDeviceName() !=
name)
903 auto primaryChip = camera->getChip(ISD::CameraChip::PRIMARY_CCD);
908 auto imageData = primaryChip->getImageData();
909 if (!imageData || imageData->hasWCS() ==
false)
912 auto x = xFactor * imageData->width();
913 auto y = yFactor * imageData->height();
917 if (imageData->pixelToWCS(point, coord))
921 mount->gotoTarget(coord);
928 void Message::processAlignCommands(
const QString &command,
const QJsonObject &payload)
932 if (align ==
nullptr)
934 qCWarning(KSTARS_EKOS) <<
"Ignoring command" << command <<
"as align module is not available";
938 if (command == commands[ALIGN_SOLVE])
943 else if (command == commands[ALIGN_SET_SETTINGS])
944 align->setSettings(payload);
945 else if (command == commands[ALIGN_STOP])
947 else if (command == commands[ALIGN_LOAD_AND_SLEW])
952 file.setAutoRemove(
false);
958 else if (command == commands[ALIGN_MANUAL_ROTATOR_TOGGLE])
960 align->toggleManualRotator(payload[
"toggled"].toBool());
964 void Message::setAlignStatus(Ekos::AlignState newState)
966 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
971 {
"status", Ekos::alignStates[newState]}
974 sendResponse(commands[NEW_ALIGN_STATE], alignState);
977 void Message::setAlignSolution(
const QVariantMap &solution)
979 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
987 sendResponse(commands[NEW_ALIGN_STATE], alignState);
990 void Message::processSchedulerCommands(
const QString &command,
const QJsonObject &payload)
994 if (command == commands[SCHEDULER_SET_PRIMARY_SETTINGS])
996 scheduler->setPrimarySettings(payload);
998 else if (command == commands[SCHEDULER_SET_JOB_STARTUP_CONDITIONS])
1000 scheduler->setJobStartupConditions(payload);
1001 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1003 else if (command == commands[SCHEDULER_SET_JOB_CONSTRAINTS])
1005 scheduler->setJobConstraints(payload);
1006 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1008 else if (command == commands[SCHEDULER_SET_JOB_COMPLETION_SETTINGS])
1010 scheduler->setJobCompletionConditions(payload);
1011 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1013 else if (command == commands[SCHEDULER_SET_OBSERVATORY_STARTUP_PROCEDURE])
1015 scheduler->setObservatoryStartupProcedure(payload);
1016 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1018 else if (command == commands[SCHEDULER_SET_ABORTED_JOB_MANAGEMENT])
1020 scheduler->setAbortedJobManagementSettings(payload);
1021 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1023 else if (command == commands[SCHEDULER_SET_OBSERVATORY_SHUTDOWN_PROCEDURE])
1025 scheduler->setObservatoryShutdownProcedure(payload);
1026 sendSchedulerSettings(m_Manager->schedulerModule()->getSchedulerSettings());
1028 else if (command == commands[SCHEDULER_GET_JOBS])
1030 sendSchedulerJobs();
1032 else if (command == commands[SCHEDULER_ADD_JOBS])
1036 else if(command == commands[SCHEDULER_REMOVE_JOBS])
1038 int index = payload[
"index"].toInt();
1041 else if(command == commands[SCHEDULER_GET_SETTINGS])
1043 sendResponse(commands[SCHEDULER_GET_SETTINGS], scheduler->getSchedulerSettings());
1045 else if(command == commands[SCHEDULER_START_JOB])
1047 scheduler->toggleScheduler();
1052 void Message::processPolarCommands(
const QString &command,
const QJsonObject &payload)
1060 if (command == commands[PAH_START])
1062 paa->startPAHProcess();
1064 if (command == commands[PAH_STOP])
1066 paa->stopPAHProcess();
1068 if (command == commands[PAH_SET_SETTINGS])
1070 paa->setPAHSettings(payload);
1072 else if (command == commands[PAH_REFRESH])
1074 paa->setPAHRefreshDuration(payload[
"value"].toDouble(1));
1075 paa->startPAHRefreshProcess();
1077 else if (command == commands[PAH_SET_ALGORITHM])
1081 algorithmCombo->
setCurrentIndex(
static_cast<Ekos::PolarAlignmentAssistant::PAHRefreshAlgorithm
>(payload[
"value"].toInt(1)));
1083 else if (command == commands[PAH_RESET_VIEW])
1085 emit resetPolarView();
1087 else if (command == commands[PAH_SET_CROSSHAIR])
1089 double x = payload[
"x"].toDouble();
1090 double y = payload[
"y"].toDouble();
1092 if (m_BoundingRect.isNull() ==
false)
1096 double boundX = x * m_BoundingRect.width();
1097 double boundY = y * m_BoundingRect.height();
1102 x = ((boundX + m_BoundingRect.x()) / (m_CurrentZoom / 100)) / m_ViewSize.width();
1103 y = ((boundY + m_BoundingRect.y()) / (m_CurrentZoom / 100)) / m_ViewSize.height();
1107 paa->setPAHCorrectionOffsetPercentage(x, y);
1109 else if (command == commands[PAH_SELECT_STAR_DONE])
1115 else if (command == commands[PAH_REFRESHING_DONE])
1117 paa->stopPAHProcess();
1119 else if (command == commands[PAH_SLEW_DONE])
1121 paa->setPAHSlewDone();
1123 else if (command == commands[PAH_PAH_SET_ZOOM])
1125 double scale = payload[
"scale"].toDouble();
1126 align->setAlignZoom(scale);
1131 void Message::setPAHStage(Ekos::PolarAlignmentAssistant::PAHStage stage)
1133 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1146 {
"stage", paa->getPAHStageString(
false)}
1151 if (stage == Ekos::PolarAlignmentAssistant::PAH_STAR_SELECT)
1152 align->zoomAlignView();
1154 sendResponse(commands[NEW_POLAR_STATE], polarState);
1159 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1169 sendResponse(commands[NEW_POLAR_STATE], polarState);
1172 void Message::setPolarResults(
QLineF correctionVector,
double polarError,
double azError,
double altError)
1174 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1177 this->correctionVector = correctionVector;
1182 {
"center_x",
center.x()},
1183 {
"center_y",
center.y()},
1184 {
"mag", correctionVector.
length()},
1185 {
"pa", correctionVector.
angle()},
1186 {
"error", polarError},
1187 {
"azError", azError},
1188 {
"altError", altError}
1196 sendResponse(commands[NEW_POLAR_STATE], polarState);
1199 void Message::setUpdatedErrors(
double total,
double az,
double alt)
1201 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1206 {
"updatedError", total},
1207 {
"updatedAZError", az},
1208 {
"updatedALTError", alt}
1211 sendResponse(commands[NEW_POLAR_STATE], error);
1214 void Message::setPAHEnabled(
bool enabled)
1216 if (m_isConnected ==
false || m_Manager->getEkosStartingStatus() != Ekos::Success)
1221 {
"enabled", enabled}
1224 sendResponse(commands[NEW_POLAR_STATE], polarState);
1227 void Message::processProfileCommands(
const QString &command,
const QJsonObject &payload)
1229 if (command == commands[START_PROFILE])
1231 if (m_Manager->getEkosStartingStatus() != Ekos::Idle)
1234 m_Manager->setProfile(payload[
"name"].
toString());
1239 else if (command == commands[STOP_PROFILE])
1246 m_PropertySubscriptions.clear();
1247 m_PropertyCache.clear();
1249 else if (command == commands[ADD_PROFILE])
1251 m_Manager->addNamedProfile(payload);
1254 else if (command == commands[UPDATE_PROFILE])
1256 m_Manager->editNamedProfile(payload);
1259 else if (command == commands[GET_PROFILE])
1261 m_Manager->getNamedProfile(payload[
"name"].
toString());
1263 else if (command == commands[DELETE_PROFILE])
1265 m_Manager->deleteNamedProfile(payload[
"name"].
toString());
1268 else if (command == commands[SET_PROFILE_MAPPING])
1270 m_Manager->setProfileMapping(payload);
1272 else if (command == commands[SET_PROFILE_PORT_SELECTION])
1274 requestPortSelection(
false);
1275 m_Manager->acceptPortSelection();
1279 void Message::sendProfiles()
1283 for (
const auto &oneProfile : m_Manager->profiles)
1284 profileArray.
append(oneProfile->toJson());
1288 {
"selectedProfile", m_Manager->getCurrentProfile()->name},
1289 {
"profiles", profileArray}
1291 sendResponse(commands[GET_PROFILES], profiles);
1294 void Message::sendSchedulerJobs()
1298 {
"jobs", m_Manager->schedulerModule()->getJSONJobs()}
1300 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1303 void Message::sendSchedulerJobList(
QJsonArray jobsList)
1309 sendResponse(commands[SCHEDULER_GET_JOBS], jobs);
1312 void Message::setEkosStatingStatus(Ekos::CommunicationStatus status)
1314 if (status == Ekos::Pending)
1319 {
"connected",
true},
1320 {
"online",
status == Ekos::Success}
1322 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
1325 void Message::processOptionsCommands(
const QString &command,
const QJsonObject &payload)
1327 if (command == commands[OPTION_SET])
1329 const QJsonArray options = payload[
"options"].toArray();
1330 for (
const auto &oneOption : options)
1331 Options::self()->setProperty(oneOption[
"name"].
toString().toLatin1(), oneOption[
"value"].toVariant());
1334 else if (command == commands[OPTION_GET])
1336 const QJsonArray options = payload[
"options"].toArray();
1338 for (
const auto &oneOption : options)
1340 const auto name = oneOption[
"name"].toString();
1341 QVariant value = Options::self()->property(
name.toLatin1());
1344 map[
"value"] = value;
1347 sendResponse(commands[OPTION_GET], result);
1350 if (command == commands[OPTION_SET_HIGH_BANDWIDTH])
1351 m_Options[OPTION_SET_HIGH_BANDWIDTH] = payload[
"value"].toBool(
true);
1352 else if (command == commands[OPTION_SET_IMAGE_TRANSFER])
1353 m_Options[OPTION_SET_IMAGE_TRANSFER] = payload[
"value"].toBool(
true);
1354 else if (command == commands[OPTION_SET_NOTIFICATIONS])
1355 m_Options[OPTION_SET_NOTIFICATIONS] = payload[
"value"].toBool(
true);
1356 else if (command == commands[OPTION_SET_CLOUD_STORAGE])
1357 m_Options[OPTION_SET_CLOUD_STORAGE] = payload[
"value"].toBool(
false);
1359 emit optionsChanged(m_Options);
1362 void Message::processScopeCommands(
const QString &command,
const QJsonObject &payload)
1364 if (command == commands[ADD_SCOPE])
1368 payload[
"type"].
toString(), payload[
"focal_length"].toDouble(), payload[
"aperture"].toDouble());
1370 else if (command == commands[UPDATE_SCOPE])
1374 payload[
"type"].
toString(), payload[
"focal_length"].toDouble(), payload[
"aperture"].toDouble(), payload[
"id"].
toString());
1376 else if (command == commands[DELETE_SCOPE])
1384 void Message::processDSLRCommands(
const QString &command,
const QJsonObject &payload)
1386 if (command == commands[DSLR_SET_INFO])
1388 if (m_Manager->captureModule())
1389 m_Manager->captureModule()->addDSLRInfo(
1391 payload[
"width"].toInt(),
1392 payload[
"height"].toInt(),
1393 payload[
"pixelw"].toDouble(),
1394 payload[
"pixelh"].toDouble());
1399 void Message::processFilterManagerCommands(
const QString &command,
const QJsonObject &payload)
1401 if (command == commands[FM_GET_DATA])
1403 QJsonObject data = m_Manager->getFilterManager()->toJSON();
1404 sendResponse(commands[FM_GET_DATA], data);
1406 else if (command == commands[FM_SET_DATA])
1408 m_Manager->getFilterManager()->setFilterData(payload);
1412 void Message::processDarkLibraryCommands(
const QString &command,
const QJsonObject &payload)
1414 if (command == commands[DARK_LIBRARY_START])
1416 Ekos::DarkLibrary::Instance()->setDarkSettings(payload);
1417 Ekos::DarkLibrary::Instance()->start();
1419 else if(command == commands[DARK_LIBRARY_SET_SETTINGS])
1421 Ekos::DarkLibrary::Instance()->setDarkSettings(payload);
1423 else if(command == commands[DARK_LIBRARY_SET_CAMERA_PRESETS])
1425 Ekos::DarkLibrary::Instance()->setCameraPresets(payload);
1427 else if (command == commands[DARK_LIBRARY_STOP])
1429 Ekos::DarkLibrary::Instance()->
stop();
1431 else if (command == commands[DARK_LIBRARY_GET_MASTERS_IMAGE])
1433 const int row = payload[
"row"].toInt();
1434 Ekos::DarkLibrary::Instance()->loadIndexInView(row);
1436 else if (command == commands[DARK_LIBRARY_GET_DARK_SETTINGS])
1438 sendResponse(commands[DARK_LIBRARY_GET_DARK_SETTINGS], Ekos::DarkLibrary::Instance()->getDarkSettings());
1440 else if (command == commands[DARK_LIBRARY_GET_CAMERA_PRESETS])
1442 sendResponse(commands[DARK_LIBRARY_GET_CAMERA_PRESETS], Ekos::DarkLibrary::Instance()->getCameraPresets());
1444 else if (command == commands[DARK_LIBRARY_SET_DEFECT_PIXELS])
1446 Ekos::DarkLibrary::Instance()->setDefectPixels(payload);
1448 else if (command == commands[DARK_LIBRARY_SAVE_MAP])
1450 Ekos::DarkLibrary::Instance()->saveMapB->click();
1452 else if (command == commands[DARK_LIBRARY_SET_DEFECT_FRAME])
1454 Ekos::DarkLibrary::Instance()->setDefectMapEnabled(
false);
1456 else if (command == commands[DARK_LIBRARY_SET_DEFECT_SETTINGS])
1458 Ekos::DarkLibrary::Instance()->setDefectSettings(payload);
1460 else if (command == commands[DARK_LIBRARY_GET_DEFECT_SETTINGS])
1462 sendResponse(commands[DARK_LIBRARY_GET_DEFECT_SETTINGS], Ekos::DarkLibrary::Instance()->getDefectSettings());
1464 else if (command == commands[DARK_LIBRARY_GET_VIEW_MASTERS])
1466 sendResponse(commands[DARK_LIBRARY_GET_VIEW_MASTERS], Ekos::DarkLibrary::Instance()->getViewMasters());
1468 else if (command == commands[DARK_LIBRARY_CLEAR_MASTERS_ROW])
1470 const int rowIndex = payload[
"row"].toInt();
1471 Ekos::DarkLibrary::Instance()->clearRow(rowIndex);
1476 void Message::processDeviceCommands(
const QString &command,
const QJsonObject &payload)
1479 QString device = payload[
"device"].toString();
1482 if (device.
isEmpty() && command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1484 m_PropertySubscriptions.clear();
1485 m_PropertyCache.clear();
1492 return (oneDevice->getDeviceName() == device);
1495 if (pos == devices.
end())
1497 auto oneDevice = *pos;
1500 if (command == commands[DEVICE_PROPERTY_GET])
1503 if (oneDevice->getJSONProperty(payload[
"property"].toString(), propObject, payload[
"compact"].toBool(
true)))
1504 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_GET]}, {
"payload", propObject}}).toJson(
1508 else if (command == commands[DEVICE_PROPERTY_SET])
1510 oneDevice->setJSONProperty(payload[
"property"].
toString(), payload[
"elements"].toArray());
1513 else if (command == commands[DEVICE_GET])
1516 for (
const auto &oneProp : *oneDevice->getProperties())
1519 if (oneDevice->getJSONProperty(oneProp->getName(), singleProp, payload[
"compact"].toBool(
false)))
1529 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_GET]}, {
"payload", response}}).toJson(
1534 else if (command == commands[DEVICE_PROPERTY_SUBSCRIBE])
1537 const QJsonArray groups = payload[
"groups"].toArray();
1541 if (m_PropertySubscriptions.contains(device))
1542 props = m_PropertySubscriptions[device];
1547 for (
const auto &oneProp : properties)
1548 props.
insert(oneProp.toString());
1551 else if (groups.
isEmpty() ==
false)
1554 for (
auto &oneProp : *oneDevice->getProperties())
1556 if (indiGroups.contains(oneProp->getGroupName()))
1557 props.
insert(oneProp->getName());
1563 for (
auto &oneProp : *oneDevice->getProperties())
1564 props.
insert(oneProp->getName());
1567 m_PropertySubscriptions[device] = props;
1569 else if (command == commands[DEVICE_PROPERTY_UNSUBSCRIBE])
1572 const QJsonArray groups = payload[
"groups"].toArray();
1576 if (m_PropertySubscriptions.contains(device))
1577 props = m_PropertySubscriptions[device];
1583 for (
const auto &oneProp : properties)
1584 props.
remove(oneProp.toString());
1587 else if (groups.
isEmpty() ==
false)
1590 for (
auto &oneProp : *oneDevice->getProperties())
1592 if (indiGroups.contains(oneProp->getGroupName()))
1593 props.
remove(oneProp->getName());
1599 for (
auto &oneProp : *oneDevice->getProperties())
1600 props.
remove(oneProp->getName());
1603 m_PropertySubscriptions[device] = props;
1607 void Message::processAstronomyCommands(
const QString &command,
const QJsonObject &payload)
1609 if (command == commands[ASTRO_GET_ALMANC])
1616 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
1620 {
"SunRise", almanac.getSunRise()},
1621 {
"SunSet", almanac.getSunSet()},
1622 {
"SunMaxAlt", almanac.getSunMaxAlt()},
1623 {
"SunMinAlt", almanac.getSunMinAlt()},
1624 {
"MoonRise", almanac.getMoonRise()},
1625 {
"MoonSet", almanac.getMoonSet()},
1626 {
"MoonPhase", almanac.getMoonPhase()},
1627 {
"MoonIllum", almanac.getMoonIllum()},
1628 {
"Dawn", almanac.getDawnAstronomicalTwilight()},
1629 {
"Dusk", almanac.getDuskAstronomicalTwilight()},
1633 sendResponse(commands[ASTRO_GET_ALMANC], response);
1636 else if (command == commands[ASTRO_SEARCH_OBJECTS])
1647 auto objectType =
static_cast<SkyObject::TYPE>(payload[
"type"].toInt(SkyObject::GALAXY));
1649 auto objectDirection =
static_cast<Direction>(payload[
"direction"].toInt(All));
1651 auto objectMaxMagnitude = payload[
"maxMagnitude"].toDouble(10);
1653 auto objectMinAlt = payload[
"minAlt"].toDouble(15);
1655 auto objectMinDuration = payload[
"minDuration"].toInt(3600);
1657 auto objectMinFOV = payload[
"minFOV"].toDouble(0);
1659 auto *data = KStarsData::Instance();
1661 auto *
geo = KStarsData::Instance()->
geo();
1664 auto start = KStarsData::Instance()->
lt();
1665 auto end = getNextDawn();
1671 CatalogsDB::CatalogObjectList dsoObjects;
1677 case SkyObject::STAR:
1678 case SkyObject::CATALOG_STAR:
1679 allObjects.
append(data->skyComposite()->objectLists(SkyObject::STAR));
1680 allObjects.
append(data->skyComposite()->objectLists(SkyObject::CATALOG_STAR));
1683 case SkyObject::PLANET:
1684 case SkyObject::MOON:
1685 allObjects.
append(data->skyComposite()->objectLists(SkyObject::PLANET));
1686 allObjects.
append(data->skyComposite()->objectLists(SkyObject::MOON));
1689 case SkyObject::COMET:
1690 allObjects.
append(data->skyComposite()->objectLists(SkyObject::COMET));
1692 case SkyObject::ASTEROID:
1693 allObjects.
append(data->skyComposite()->objectLists(SkyObject::ASTEROID));
1696 case SkyObject::OPEN_CLUSTER:
1697 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::OPEN_CLUSTER, objectMaxMagnitude));
1700 case SkyObject::GLOBULAR_CLUSTER:
1701 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GLOBULAR_CLUSTER, objectMaxMagnitude));
1705 case SkyObject::GASEOUS_NEBULA:
1706 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GASEOUS_NEBULA, objectMaxMagnitude));
1709 case SkyObject::PLANETARY_NEBULA:
1710 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::PLANETARY_NEBULA, objectMaxMagnitude));
1713 case SkyObject::GALAXY:
1714 dsoObjects.splice(dsoObjects.end(), m_DSOManager.get_objects(SkyObject::GALAXY, objectMaxMagnitude));
1717 case SkyObject::SUPERNOVA:
1719 if (!Options::showSupernovae())
1721 Options::setShowSupernovae(
true);
1722 data->setFullTimeUpdate();
1725 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SUPERNOVA));
1728 case SkyObject::SATELLITE:
1730 if (!Options::showSatellites())
1732 Options::setShowSatellites(
true);
1733 data->setFullTimeUpdate();
1736 allObjects.
append(data->skyComposite()->objectLists(SkyObject::SATELLITE));
1744 std::sort(allObjects.
begin(), allObjects.
end(), [](
const auto & a,
const auto & b)
1746 return a.second->mag() < b.second->mag();
1752 if (objectDirection != All)
1754 QPair<int, int> Quardent1(270, 360), Quardent2(0, 90), Quardent3(90, 180), Quardent4(180, 270);
1756 switch (objectDirection)
1780 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1781 while (dsoIterator != dsoObjects.end())
1784 const double az = (*dsoIterator).recomputeHorizontalCoords(start, geo).az().Degrees();
1785 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1786 dsoIterator = dsoObjects.erase(dsoIterator);
1793 while (objectIterator.hasNext())
1795 const auto az = objectIterator.next().second->recomputeHorizontalCoords(start, geo).az().Degrees();
1796 if (! ((minAZ.first <= az && az <= minAZ.second) || (maxAZ.first <= az && az <= maxAZ.second)))
1797 objectIterator.remove();
1805 objectIterator.toFront();
1806 while (objectIterator.hasNext())
1808 auto magnitude = objectIterator.next().second->mag();
1810 if (magnitude != NaN::f && magnitude > objectMaxMagnitude)
1811 objectIterator.remove();
1818 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1819 while (dsoIterator != dsoObjects.end())
1821 double duration = 0;
1824 dms LST =
geo->GSTtoLST(t.gst());
1825 (*dsoIterator).EquatorialToHorizontal(&LST,
geo->lat());
1826 if ((*dsoIterator).alt().Degrees() >= objectMinAlt)
1830 if (duration < objectMinDuration)
1831 dsoIterator = dsoObjects.erase(dsoIterator);
1838 objectIterator.toFront();
1839 while (objectIterator.hasNext())
1841 auto oneObject = objectIterator.next().second;
1842 double duration = 0;
1846 auto LST =
geo->GSTtoLST(t.gst());
1847 const_cast<SkyObject *
>(oneObject)->EquatorialToHorizontal(&LST,
geo->lat());
1848 if (oneObject->alt().Degrees() >= objectMinAlt)
1852 if (duration < objectMinDuration)
1853 objectIterator.remove();
1858 if (isDSO && objectMinFOV > 0)
1860 CatalogsDB::CatalogObjectList::iterator dsoIterator = dsoObjects.begin();
1861 while (dsoIterator != dsoObjects.end())
1863 if ((*dsoIterator).a() < objectMinFOV)
1864 dsoIterator = dsoObjects.erase(dsoIterator);
1871 for (
auto &oneObject : allObjects)
1872 searchObjects.
append(oneObject.second->name());
1873 for (
auto &oneObject : dsoObjects)
1874 searchObjects.
append(oneObject.name());
1879 sendResponse(commands[ASTRO_SEARCH_OBJECTS], response);
1881 else if(command == commands[ASTRO_GET_OBJECT_INFO])
1883 const auto name = payload[
"object"].toString();
1892 {
"magnitude", oneObject->
mag()},
1895 {
"ra", oneObject->
ra().
Hours()},
1899 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info);
1908 sendResponse(commands[ASTRO_GET_OBJECT_INFO], info );
1913 else if (command == commands[ASTRO_GET_OBJECTS_INFO])
1923 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
1926 for (
auto &oneName : objectNames)
1936 {
"magnitude", oneObject->
mag()},
1939 {
"ra", oneObject->
ra().
Hours()},
1947 info[
"a"] = dsoObject->
a();
1948 info[
"b"] = dsoObject->
b();
1949 info[
"pa"] = dsoObject->
pa();
1952 objectsArray.
append(info);
1956 sendResponse(commands[ASTRO_GET_OBJECTS_INFO], objectsArray);
1959 else if (command == commands[ASTRO_GET_OBJECTS_OBSERVABILITY])
1969 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
1973 auto *data = KStarsData::Instance();
1975 auto *
geo = KStarsData::Instance()->
geo();
1977 auto ut = data->ut();
1979 for (
auto &oneName : objectNames)
1982 SkyObject *oneObject = data->skyComposite()->findByName(name,
false);
1986 dms ha(data->lst()->Degrees() - oneObject->
ra().
Degrees());
1995 objectsArray.
append(info);
1999 sendResponse(commands[ASTRO_GET_OBJECTS_OBSERVABILITY], objectsArray);
2001 else if (command == commands[ASTRO_GET_OBJECTS_RISESET])
2011 QVariantList objectNames = payload[
"names"].toArray().toVariantList();
2015 auto *data = KStarsData::Instance();
2017 auto *
geo = KStarsData::Instance()->
geo();
2023 if (data->lt().time().hour() > 12)
2026 for (
auto &oneName : objectNames)
2029 SkyObject *oneObject = data->skyComposite()->findByName(name,
false);
2039 if (transitTime < riseTime)
2046 if (setTime < riseTime)
2049 info[
"name"] =
name;
2059 info[
"rise"] =
"Circumpolar";
2060 info[
"set"] =
"Circumpolar";
2064 info[
"rise"] =
"Never rises";
2065 info[
"set"] =
"Never rises";
2072 for (
double h = -12.0; h <= 12.0; h += 0.5)
2074 double hour = h + (24.0 * DayOffset);
2081 info[
"altitudes"] = altitudes;
2083 objectsArray.
append(info);
2087 sendResponse(commands[ASTRO_GET_OBJECTS_RISESET], objectsArray);
2098 KSAlmanac almanac(midnight, KStarsData::Instance()->
geo());
2102 if (nextDawn < localTime)
2108 void Message::requestDSLRInfo(
const QString &cameraName)
2110 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DSLR_GET_INFO]}, {
"payload", cameraName}}).toJson(
2114 void Message::requestPortSelection(
bool show)
2116 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[GET_PROFILE_PORT_SELECTION]}, {
"payload", show}}).toJson(
2122 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DIALOG_GET_INFO]}, {
"payload",
message}}).toJson(
2136 void Message::updateMountStatus(
const QJsonObject &status,
bool throttle)
2138 if (m_isConnected ==
false)
2144 if (m_ThrottleTS.msecsTo(now) >= THROTTLE_INTERVAL)
2147 sendResponse(commands[NEW_MOUNT_STATE], status);
2151 sendResponse(commands[NEW_MOUNT_STATE], status);
2154 void Message::updateCaptureStatus(
const QJsonObject &status)
2156 if (m_isConnected ==
false)
2159 sendResponse(commands[NEW_CAPTURE_STATE], status);
2162 void Message::updateFocusStatus(
const QJsonObject &status)
2164 if (m_isConnected ==
false)
2167 sendResponse(commands[NEW_FOCUS_STATE], status);
2170 void Message::updateGuideStatus(
const QJsonObject &status)
2172 if (m_isConnected ==
false)
2175 sendResponse(commands[NEW_GUIDE_STATE], status);
2178 void Message::updateDomeStatus(
const QJsonObject &status)
2180 if (m_isConnected ==
false)
2183 sendResponse(commands[NEW_DOME_STATE], status);
2186 void Message::updateCapStatus(
const QJsonObject &status)
2188 if (m_isConnected ==
false)
2191 sendResponse(commands[NEW_CAP_STATE], status);
2194 void Message::sendConnection()
2196 if (m_isConnected ==
false)
2201 {
"connected",
true},
2202 {
"online", m_Manager->getEkosStartingStatus() == Ekos::Success}
2204 sendResponse(commands[NEW_CONNECTION_STATE], connectionState);
2207 void Message::sendStates()
2209 if (m_isConnected ==
false)
2213 if (m_Manager->captureModule())
2215 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2216 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2217 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2220 if (m_Manager->mountModule())
2224 {
"status", m_Manager->mountModule()->statusString(
false)},
2225 {
"target", m_Manager->mountTarget->text()},
2226 {
"slewRate", m_Manager->mountModule()->slewRate()},
2227 {
"pierSide", m_Manager->mountModule()->pierSide()}
2230 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2233 if (m_Manager->focusModule())
2235 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->status(),
false)}};
2236 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2239 if (m_Manager->guideModule())
2241 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2242 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2245 if (m_Manager->alignModule())
2250 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2252 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2255 sendResponse(commands[ALIGN_SET_SETTINGS], m_Manager->alignModule()->getSettings());
2262 doc.
setHtml(paa->getPAHMessage());
2265 {
"stage", paa->getPAHStageString(
false)},
2269 sendResponse(commands[NEW_POLAR_STATE], polarState);
2273 sendResponse(commands[PAH_SET_SETTINGS], paa->getPAHSettings());
2278 void Message::sendEvent(
const QString &
message, KSNotification::EventType event)
2280 if (m_isConnected ==
false || m_Options[OPTION_SET_NOTIFICATIONS] ==
false)
2284 sendResponse(commands[NEW_NOTIFICATION], newEvent);
2287 void Message::sendManualRotatorStatus(
double currentPA,
double targetPA,
double threshold)
2289 if (m_isConnected ==
false)
2292 QJsonObject request = {{
"currentPA", currentPA}, {
"targetPA", targetPA}, {
"threshold", threshold}};
2293 sendResponse(commands[ALIGN_MANUAL_ROTATOR_STATUS], request);
2296 void Message::setBoundingRect(
QRect rect,
QSize view,
double currentZoom)
2298 m_BoundingRect = rect;
2300 m_CurrentZoom = currentZoom;
2303 void Message::processDialogResponse(
const QJsonObject &payload)
2308 void Message::processNewProperty(INDI::Property prop)
2313 if (m_Manager->settleStatus() != Ekos::CommunicationStatus::Success)
2317 ISD::propertyToJson(prop, propObject,
false);
2318 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_ADD]}, {
"payload", propObject}}).toJson(
2322 void Message::processDeleteProperty(
const QString &device,
const QString &name)
2330 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_REMOVE]}, {
"payload", payload}}).toJson(
2334 void Message::processNewNumber(INumberVectorProperty * nvp)
2336 if (m_PropertySubscriptions.contains(nvp->device))
2338 QSet<QString> subProps = m_PropertySubscriptions[nvp->device];
2342 ISD::propertyToJson(nvp, *propObject);
2344 if (m_PropertyCache.contains(nvp->name) && *m_PropertyCache[nvp->name] == *propObject)
2346 delete (propObject);
2350 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_GET]}, {
"payload", *propObject}}).toJson(
2352 m_PropertyCache.insert(nvp->name, propObject);
2357 void Message::processNewText(ITextVectorProperty * tvp)
2359 if (m_PropertySubscriptions.contains(tvp->device))
2361 QSet<QString> subProps = m_PropertySubscriptions[tvp->device];
2365 ISD::propertyToJson(tvp, *propObject);
2367 if (m_PropertyCache.contains(tvp->name) && *m_PropertyCache[tvp->name] == *propObject)
2369 delete (propObject);
2373 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_GET]}, {
"payload", *propObject}}).toJson(
2375 m_PropertyCache.insert(tvp->name, propObject);
2380 void Message::processNewSwitch(ISwitchVectorProperty * svp)
2382 if (m_PropertySubscriptions.contains(svp->device))
2384 QSet<QString> subProps = m_PropertySubscriptions[svp->device];
2388 ISD::propertyToJson(svp, *propObject);
2390 if (m_PropertyCache.contains(svp->name) && *m_PropertyCache[svp->name] == *propObject)
2392 delete (propObject);
2396 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_GET]}, {
"payload", *propObject}}).toJson(
2398 m_PropertyCache.insert(svp->name, propObject);
2403 void Message::processNewLight(ILightVectorProperty * lvp)
2405 if (m_PropertySubscriptions.contains(lvp->device))
2407 QSet<QString> subProps = m_PropertySubscriptions[lvp->device];
2411 ISD::propertyToJson(lvp, propObject);
2412 m_WebSocket.sendTextMessage(
QJsonDocument({{
"type", commands[DEVICE_PROPERTY_GET]}, {
"payload", propObject}}).toJson(
2418 void Message::sendModuleState(
const QString &name)
2420 if (m_isConnected ==
false)
2423 if (name ==
"Capture")
2425 QJsonObject captureState = {{
"status", getCaptureStatusString(m_Manager->captureModule()->status(),
false)}};
2426 sendResponse(commands[NEW_CAPTURE_STATE], captureState);
2427 sendCaptureSequence(m_Manager->captureModule()->getSequence());
2429 else if (name ==
"Mount")
2433 {
"status", m_Manager->mountStatus->text()},
2434 {
"target", m_Manager->mountTarget->text()},
2435 {
"slewRate", m_Manager->mountModule()->slewRate()},
2436 {
"pierSide", m_Manager->mountModule()->pierSide()}
2439 sendResponse(commands[NEW_MOUNT_STATE], mountState);
2441 else if (name ==
"Focus")
2443 QJsonObject focusState = {{
"status", getFocusStatusString(m_Manager->focusModule()->status(),
false)}};
2444 sendResponse(commands[NEW_FOCUS_STATE], focusState);
2446 else if (name ==
"Guide")
2448 QJsonObject guideState = {{
"status", getGuideStatusString(m_Manager->guideModule()->status(),
false)}};
2449 sendResponse(commands[NEW_GUIDE_STATE], guideState);
2451 else if (name ==
"Align")
2456 {
"status", getAlignStatusString(m_Manager->alignModule()->status(),
false)}
2458 sendResponse(commands[NEW_ALIGN_STATE], alignState);
2461 sendResponse(commands[ALIGN_SET_SETTINGS], m_Manager->alignModule()->getSettings());
2468 doc.
setHtml(paa->getPAHMessage());
2471 {
"stage", paa->getPAHStageString(
false)},
2475 sendResponse(commands[NEW_POLAR_STATE], polarState);
2478 sendResponse(commands[PAH_SET_SETTINGS], paa->getPAHSettings());