Warning, file /education/kstars/kstars/ekos/align/remoteastrometryparser.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "remoteastrometryparser.h" 0008 0009 #include "align.h" 0010 #include "ekos_align_debug.h" 0011 #include "Options.h" 0012 #include "indi/clientmanager.h" 0013 #include "indi/driverinfo.h" 0014 #include "indi/guimanager.h" 0015 #include "indi/indidevice.h" 0016 0017 #include <indicom.h> 0018 0019 #include <KMessageBox> 0020 0021 namespace Ekos 0022 { 0023 RemoteAstrometryParser::RemoteAstrometryParser() : AstrometryParser() 0024 { 0025 } 0026 0027 bool RemoteAstrometryParser::init() 0028 { 0029 if (m_RemoteAstrometry == nullptr) 0030 { 0031 align->appendLogText( 0032 i18n("Cannot set solver to remote. The Ekos equipment profile must include the astrometry Auxiliary driver.")); 0033 return false; 0034 } 0035 0036 return true; 0037 } 0038 0039 void RemoteAstrometryParser::verifyIndexFiles(double, double) 0040 { 0041 } 0042 0043 bool RemoteAstrometryParser::startSolver(const QString &filename, const QStringList &args, bool generated) 0044 { 0045 INDI_UNUSED(generated); 0046 0047 QFile fp(filename); 0048 if (fp.open(QIODevice::ReadOnly) == false) 0049 { 0050 align->appendLogText(i18n("Cannot open file %1 for reading.", filename)); 0051 emit solverFailed(); 0052 return false; 0053 } 0054 0055 auto solverSwitch = m_RemoteAstrometry->getProperty("ASTROMETRY_SOLVER").getSwitch(); 0056 auto solverBLOB = m_RemoteAstrometry->getProperty("ASTROMETRY_DATA").getBLOB(); 0057 0058 if (solverSwitch->isEmpty() || solverBLOB->isEmpty()) 0059 { 0060 align->appendLogText(i18n("Failed to find solver properties.")); 0061 fp.close(); 0062 emit solverFailed(); 0063 return false; 0064 } 0065 0066 sendArgs(args); 0067 0068 auto enableSW = solverSwitch->findWidgetByName("ASTROMETRY_SOLVER_ENABLE"); 0069 if (enableSW->getState() == ISS_OFF) 0070 { 0071 solverSwitch->reset(); 0072 enableSW->setState(ISS_ON); 0073 m_RemoteAstrometry->sendNewProperty(solverSwitch); 0074 } 0075 0076 // #PS: TODO 0077 auto bp = solverBLOB->at(0); 0078 0079 bp->setBlobLen(fp.size()); 0080 bp->setSize(fp.size()); 0081 0082 bp->setBlob(static_cast<uint8_t *>(realloc(bp->getBlob(), bp->getSize()))); 0083 if (bp->getBlob() == nullptr) 0084 { 0085 align->appendLogText(i18n("Not enough memory for file %1.", filename)); 0086 fp.close(); 0087 emit solverFailed(); 0088 return false; 0089 } 0090 0091 memcpy(bp->blob, fp.readAll().constData(), bp->size); 0092 0093 solverRunning = true; 0094 0095 m_RemoteAstrometry->getDriverInfo()->getClientManager()->startBlob(solverBLOB->getDeviceName(), solverBLOB->getName(), 0096 QDateTime::currentDateTimeUtc().toString(Qt::ISODate).remove("Z").toLatin1().constData()); 0097 0098 m_RemoteAstrometry->getDriverInfo()->getClientManager()->sendOneBlob(bp); 0099 0100 m_RemoteAstrometry->getDriverInfo()->getClientManager()->finishBlob(); 0101 0102 align->appendLogText(i18n("Starting remote solver...")); 0103 return true; 0104 } 0105 0106 bool RemoteAstrometryParser::sendArgs(const QStringList &args) 0107 { 0108 auto solverSettings = m_RemoteAstrometry->getBaseDevice().getText("ASTROMETRY_SETTINGS"); 0109 0110 if (!solverSettings) 0111 { 0112 align->appendLogText(i18n("Failed to find solver settings.")); 0113 emit solverFailed(); 0114 return false; 0115 } 0116 0117 QStringList solverArgs = args; 0118 // Add parity option if none is give and we already know parity before 0119 // and is NOT a blind solve 0120 if (Options::astrometryDetectParity() && args.contains("parity") == false && 0121 (args.contains("-3") || args.contains("-L"))) 0122 solverArgs << "--parity" << QString::number(parity); 0123 0124 //for (int i = 0; i < solverSettings->ntp; i++) 0125 for (auto it : solverSettings) 0126 { 0127 // 2016-10-20: Disable setting this automatically since remote device might have different 0128 // settings 0129 /*if (!strcmp(solverSettings->tp[i].name, "ASTROMETRY_SETTINGS_BINARY")) 0130 IUSaveText(&solverSettings->tp[i], Options::astrometrySolver().toLatin1().constData());*/ 0131 if (it.isNameMatch("ASTROMETRY_SETTINGS_OPTIONS")) 0132 it.setText(solverArgs.join(" ").toLatin1().constData()); 0133 } 0134 0135 m_RemoteAstrometry->sendNewProperty(solverSettings); 0136 INDI_D *guiDevice = GUIManager::Instance()->findGUIDevice(m_RemoteAstrometry->getDeviceName()); 0137 if (guiDevice) 0138 guiDevice->updateTextGUI(solverSettings); 0139 0140 return true; 0141 } 0142 0143 void RemoteAstrometryParser::setEnabled(bool enable) 0144 { 0145 auto solverSwitch = m_RemoteAstrometry->getBaseDevice().getSwitch("ASTROMETRY_SOLVER"); 0146 0147 if (!solverSwitch) 0148 return; 0149 0150 auto enableSW = solverSwitch.findWidgetByName("ASTROMETRY_SOLVER_ENABLE"); 0151 auto disableSW = solverSwitch.findWidgetByName("ASTROMETRY_SOLVER_DISABLE"); 0152 0153 if (!enableSW || !disableSW) 0154 return; 0155 0156 if (enable && enableSW->getState() == ISS_OFF) 0157 { 0158 solverSwitch.reset(); 0159 enableSW->setState(ISS_ON); 0160 m_RemoteAstrometry->sendNewProperty(solverSwitch); 0161 solverRunning = true; 0162 qCDebug(KSTARS_EKOS_ALIGN) << "Enabling remote solver..."; 0163 } 0164 else if (enable == false && disableSW->s == ISS_OFF) 0165 { 0166 solverSwitch.reset(); 0167 disableSW->setState(ISS_ON); 0168 m_RemoteAstrometry->sendNewProperty(solverSwitch); 0169 solverRunning = false; 0170 qCDebug(KSTARS_EKOS_ALIGN) << "Disabling remote solver..."; 0171 } 0172 } 0173 0174 bool RemoteAstrometryParser::setCCD(const QString &ccd) 0175 { 0176 targetCCD = ccd; 0177 0178 if (!m_RemoteAstrometry) 0179 return false; 0180 0181 auto activeDevices = m_RemoteAstrometry->getBaseDevice().getText("ACTIVE_DEVICES"); 0182 0183 if (!activeDevices) 0184 return false; 0185 0186 auto activeCCD = activeDevices.findWidgetByName("ACTIVE_CCD"); 0187 0188 if (!activeCCD) 0189 return false; 0190 0191 // If same device, no need to update 0192 if (QString(activeCCD->getText()) == ccd) 0193 return true; 0194 0195 activeCCD->setText(ccd.toLatin1().data()); 0196 m_RemoteAstrometry->sendNewProperty(activeDevices); 0197 0198 return true; 0199 } 0200 0201 bool RemoteAstrometryParser::stopSolver() 0202 { 0203 if (solverRunning == false) 0204 return true; 0205 0206 // Disable solver 0207 auto svp = m_RemoteAstrometry->getProperty("ASTROMETRY_SOLVER").getSwitch(); 0208 if (svp->isEmpty()) 0209 return false; 0210 0211 auto disableSW = svp->findWidgetByName("ASTROMETRY_SOLVER_DISABLE"); 0212 if (disableSW->getState() == ISS_OFF) 0213 { 0214 svp->reset(); 0215 disableSW->setState(ISS_ON); 0216 m_RemoteAstrometry->sendNewProperty(svp); 0217 } 0218 0219 solverRunning = false; 0220 0221 return true; 0222 } 0223 0224 void RemoteAstrometryParser::setAstrometryDevice(const QSharedPointer<ISD::GenericDevice> &device) 0225 { 0226 if (device == m_RemoteAstrometry) 0227 return; 0228 0229 m_RemoteAstrometry = device; 0230 0231 m_RemoteAstrometry->disconnect(this); 0232 0233 connect(m_RemoteAstrometry.get(), &ISD::GenericDevice::propertyUpdated, this, &RemoteAstrometryParser::checkStatus); 0234 connect(m_RemoteAstrometry.get(), &ISD::GenericDevice::propertyUpdated, this, &RemoteAstrometryParser::checkResults); 0235 0236 if (targetCCD.isEmpty() == false) 0237 setCCD(targetCCD); 0238 } 0239 0240 void RemoteAstrometryParser::checkStatus(INDI::Property prop) 0241 { 0242 if (solverRunning == false || !prop.isNameMatch("ASTROMETRY_SOLVER")) 0243 return; 0244 0245 if (prop.getState() == IPS_ALERT) 0246 { 0247 stopSolver(); 0248 align->appendLogText(i18n("Solver failed. Try again.")); 0249 emit solverFailed(); 0250 return; 0251 } 0252 } 0253 0254 void RemoteAstrometryParser::checkResults(INDI::Property prop) 0255 { 0256 if (solverRunning == false || !prop.isNameMatch("ASTROMETRY_RESULTS") || prop.getState() != IPS_OK) 0257 return; 0258 0259 double pixscale, ra, de, orientation; 0260 pixscale = ra = de = orientation = -1000; 0261 0262 auto nvp = prop.getNumber(); 0263 0264 for (int i = 0; i < nvp->count(); i++) 0265 { 0266 auto value = nvp->at(i)->getValue(); 0267 if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_PIXSCALE")) 0268 pixscale = value; 0269 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_ORIENTATION")) 0270 orientation = value; 0271 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_RA")) 0272 ra = value; 0273 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_DE")) 0274 de = value; 0275 else if (nvp->at(i)->isNameMatch("ASTROMETRY_RESULTS_PARITY")) 0276 { 0277 if (value == 1) 0278 parity = FITSImage::POSITIVE; 0279 else if (value == -1) 0280 parity = FITSImage::NEGATIVE; 0281 } 0282 } 0283 0284 if (pixscale != -1000 && ra != -1000 && de != -1000 && orientation != -1000) 0285 { 0286 stopSolver(); 0287 emit solverFinished(orientation, ra, de, pixscale, parity != FITSImage::POSITIVE); 0288 } 0289 } 0290 }