Kstars

remoteastrometryparser.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "remoteastrometryparser.h"
8
9#include "align.h"
10#include "ekos_align_debug.h"
11#include "Options.h"
12#include "indi/clientmanager.h"
13#include "indi/driverinfo.h"
14#include "indi/guimanager.h"
15#include "indi/indidevice.h"
16
17#include <indicom.h>
18
19#include <KMessageBox>
20
21namespace Ekos
22{
23RemoteAstrometryParser::RemoteAstrometryParser() : AstrometryParser()
24{
25}
26
27bool RemoteAstrometryParser::init()
28{
29 if (m_RemoteAstrometry == nullptr)
30 {
31 align->appendLogText(
32 i18n("Cannot set solver to remote. The Ekos equipment profile must include the astrometry Auxiliary driver."));
33 return false;
34 }
35
36 return true;
37}
38
39void RemoteAstrometryParser::verifyIndexFiles(double, double)
40{
41}
42
43bool RemoteAstrometryParser::startSolver(const QString &filename, const QStringList &args, bool generated)
44{
46
47 QFile fp(filename);
48 if (fp.open(QIODevice::ReadOnly) == false)
49 {
50 align->appendLogText(i18n("Cannot open file %1 for reading.", filename));
51 emit solverFailed();
52 return false;
53 }
54
55 auto solverSwitch = m_RemoteAstrometry->getProperty("ASTROMETRY_SOLVER").getSwitch();
56 auto solverBLOB = m_RemoteAstrometry->getProperty("ASTROMETRY_DATA").getBLOB();
57
58 if (solverSwitch->isEmpty() || solverBLOB->isEmpty())
59 {
60 align->appendLogText(i18n("Failed to find solver properties."));
61 fp.close();
62 emit solverFailed();
63 return false;
64 }
65
66 sendArgs(args);
67
68 auto enableSW = solverSwitch->findWidgetByName("ASTROMETRY_SOLVER_ENABLE");
69 if (enableSW->getState() == ISS_OFF)
70 {
71 solverSwitch->reset();
72 enableSW->setState(ISS_ON);
73 m_RemoteAstrometry->sendNewProperty(solverSwitch);
74 }
75
76 // #PS: TODO
77 auto bp = solverBLOB->at(0);
78
79 bp->setBlobLen(fp.size());
80 bp->setSize(fp.size());
81
82 bp->setBlob(static_cast<uint8_t *>(realloc(bp->getBlob(), bp->getSize())));
83 if (bp->getBlob() == nullptr)
84 {
85 align->appendLogText(i18n("Not enough memory for file %1.", filename));
86 fp.close();
87 emit solverFailed();
88 return false;
89 }
90
91 memcpy(bp->blob, fp.readAll().constData(), bp->size);
92
93 solverRunning = true;
94
95 m_RemoteAstrometry->getDriverInfo()->getClientManager()->startBlob(solverBLOB->getDeviceName(), solverBLOB->getName(),
97
98 m_RemoteAstrometry->getDriverInfo()->getClientManager()->sendOneBlob(bp);
99
100 m_RemoteAstrometry->getDriverInfo()->getClientManager()->finishBlob();
101
102 align->appendLogText(i18n("Starting remote solver..."));
103 return true;
104}
105
106bool RemoteAstrometryParser::sendArgs(const QStringList &args)
107{
108 auto solverSettings = m_RemoteAstrometry->getBaseDevice().getText("ASTROMETRY_SETTINGS");
109
110 if (!solverSettings)
111 {
112 align->appendLogText(i18n("Failed to find solver settings."));
113 emit solverFailed();
114 return false;
115 }
116
118 // Add parity option if none is give and we already know parity before
119 // and is NOT a blind solve
120 if (Options::astrometryDetectParity() && args.contains("parity") == false &&
121 (args.contains("-3") || args.contains("-L")))
122 solverArgs << "--parity" << QString::number(parity);
123
124 //for (int i = 0; i < solverSettings->ntp; i++)
125 for (auto it : solverSettings)
126 {
127 // 2016-10-20: Disable setting this automatically since remote device might have different
128 // settings
129 /*if (!strcmp(solverSettings->tp[i].name, "ASTROMETRY_SETTINGS_BINARY"))
130 IUSaveText(&solverSettings->tp[i], Options::astrometrySolver().toLatin1().constData());*/
131 if (it.isNameMatch("ASTROMETRY_SETTINGS_OPTIONS"))
132 it.setText(solverArgs.join(" ").toLatin1().constData());
133 }
134
135 m_RemoteAstrometry->sendNewProperty(solverSettings);
136 INDI_D *guiDevice = GUIManager::Instance()->findGUIDevice(m_RemoteAstrometry->getDeviceName());
137 if (guiDevice)
138 guiDevice->updateTextGUI(solverSettings);
139
140 return true;
141}
142
143void RemoteAstrometryParser::setEnabled(bool enable)
144{
145 auto solverSwitch = m_RemoteAstrometry->getBaseDevice().getSwitch("ASTROMETRY_SOLVER");
146
147 if (!solverSwitch)
148 return;
149
150 auto enableSW = solverSwitch.findWidgetByName("ASTROMETRY_SOLVER_ENABLE");
151 auto disableSW = solverSwitch.findWidgetByName("ASTROMETRY_SOLVER_DISABLE");
152
153 if (!enableSW || !disableSW)
154 return;
155
156 if (enable && enableSW->getState() == ISS_OFF)
157 {
158 solverSwitch.reset();
159 enableSW->setState(ISS_ON);
160 m_RemoteAstrometry->sendNewProperty(solverSwitch);
161 solverRunning = true;
162 qCDebug(KSTARS_EKOS_ALIGN) << "Enabling remote solver...";
163 }
164 else if (enable == false && disableSW->s == ISS_OFF)
165 {
166 solverSwitch.reset();
167 disableSW->setState(ISS_ON);
168 m_RemoteAstrometry->sendNewProperty(solverSwitch);
169 solverRunning = false;
170 qCDebug(KSTARS_EKOS_ALIGN) << "Disabling remote solver...";
171 }
172}
173
174bool RemoteAstrometryParser::setCCD(const QString &ccd)
175{
176 targetCCD = ccd;
177
178 if (!m_RemoteAstrometry)
179 return false;
180
181 auto activeDevices = m_RemoteAstrometry->getBaseDevice().getText("ACTIVE_DEVICES");
182
183 if (!activeDevices)
184 return false;
185
186 auto activeCCD = activeDevices.findWidgetByName("ACTIVE_CCD");
187
188 if (!activeCCD)
189 return false;
190
191 // If same device, no need to update
192 if (QString(activeCCD->getText()) == ccd)
193 return true;
194
195 activeCCD->setText(ccd.toLatin1().data());
196 m_RemoteAstrometry->sendNewProperty(activeDevices);
197
198 return true;
199}
200
201bool RemoteAstrometryParser::stopSolver()
202{
203 if (solverRunning == false)
204 return true;
205
206 // Disable solver
207 auto svp = m_RemoteAstrometry->getProperty("ASTROMETRY_SOLVER").getSwitch();
208 if (svp->isEmpty())
209 return false;
210
211 auto disableSW = svp->findWidgetByName("ASTROMETRY_SOLVER_DISABLE");
212 if (disableSW->getState() == ISS_OFF)
213 {
214 svp->reset();
215 disableSW->setState(ISS_ON);
216 m_RemoteAstrometry->sendNewProperty(svp);
217 }
218
219 solverRunning = false;
220
221 return true;
222}
223
224void RemoteAstrometryParser::setAstrometryDevice(const QSharedPointer<ISD::GenericDevice> &device)
225{
226 if (device == m_RemoteAstrometry)
227 return;
228
229 m_RemoteAstrometry = device;
230
231 m_RemoteAstrometry->disconnect(this);
232
233 connect(m_RemoteAstrometry.get(), &ISD::GenericDevice::propertyUpdated, this, &RemoteAstrometryParser::checkStatus);
234 connect(m_RemoteAstrometry.get(), &ISD::GenericDevice::propertyUpdated, this, &RemoteAstrometryParser::checkResults);
235
236 if (targetCCD.isEmpty() == false)
237 setCCD(targetCCD);
238}
239
240void RemoteAstrometryParser::checkStatus(INDI::Property prop)
241{
242 if (solverRunning == false || !prop.isNameMatch("ASTROMETRY_SOLVER"))
243 return;
244
245 if (prop.getState() == IPS_ALERT)
246 {
247 stopSolver();
248 align->appendLogText(i18n("Solver failed. Try again."));
249 emit solverFailed();
250 return;
251 }
252}
253
254void RemoteAstrometryParser::checkResults(INDI::Property prop)
255{
256 if (solverRunning == false || !prop.isNameMatch("ASTROMETRY_RESULTS") || prop.getState() != IPS_OK)
257 return;
258
259 double pixscale, ra, de, orientation;
260 pixscale = ra = de = orientation = -1000;
261
262 auto nvp = prop.getNumber();
263
264 for (int i = 0; i < nvp->count(); i++)
265 {
266 auto value = nvp->at(i)->getValue();
267 if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_PIXSCALE"))
268 pixscale = value;
269 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_ORIENTATION"))
270 orientation = value;
271 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_RA"))
272 ra = value;
273 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_DE"))
274 de = value;
275 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_PARITY"))
276 {
277 if (value == 1)
278 parity = FITSImage::POSITIVE;
279 else if (value == -1)
280 parity = FITSImage::NEGATIVE;
281 }
282 }
283
284 if (pixscale != -1000 && ra != -1000 && de != -1000 && orientation != -1000)
285 {
286 stopSolver();
287 emit solverFinished(orientation, ra, de, pixscale, parity != FITSImage::POSITIVE);
288 }
289}
290}
INDI_D represents an INDI GUI Device.
Definition indidevice.h:35
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:78
const char * constData() const const
char * data()
QDateTime currentDateTimeUtc()
QString toString(QStringView format, QCalendar cal) const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QByteArray toLatin1() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.