File indexing completed on 2024-04-28 07:31:47
0001 /* 0002 SPDX-FileCopyrightText: 2014 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "indidbus.h" 0008 0009 #include "indiadaptor.h" 0010 #include "nan.h" 0011 #include "indi/drivermanager.h" 0012 #include "indi/driverinfo.h" 0013 #include "indi/clientmanager.h" 0014 #include "indi/indilistener.h" 0015 #include "indi/indiconcretedevice.h" 0016 #include "indi/deviceinfo.h" 0017 0018 #include "kstars_debug.h" 0019 0020 #include <basedevice.h> 0021 0022 INDIDBus::INDIDBus(QObject *parent) : QObject(parent) 0023 { 0024 new INDIAdaptor(this); 0025 QDBusConnection::sessionBus().registerObject("/KStars/INDI", this); 0026 } 0027 0028 bool INDIDBus::start(int port, const QStringList &drivers) 0029 { 0030 QList<QSharedPointer<DriverInfo>> newDrivers; 0031 0032 for (auto &driver : drivers) 0033 { 0034 auto drv = DriverManager::Instance()->findDriverByExec(driver); 0035 0036 if (drv == nullptr) 0037 continue; 0038 0039 QSharedPointer<DriverInfo> di(new DriverInfo(QString("%1").arg(driver))); 0040 di->setHostParameters("localhost", port); 0041 di->setDriverSource(EM_XML); 0042 di->setExecutable(driver); 0043 di->setUniqueLabel(drv->getUniqueLabel().isEmpty() ? drv->getLabel() : drv->getUniqueLabel()); 0044 0045 DriverManager::Instance()->addDriver(di); 0046 newDrivers.append(di); 0047 } 0048 0049 DriverManager::Instance()->startDevices(newDrivers); 0050 return true; 0051 } 0052 0053 bool INDIDBus::stop(const QString &port) 0054 { 0055 QList<QSharedPointer<DriverInfo>> stopDrivers; 0056 0057 foreach (QSharedPointer<DriverInfo>di, DriverManager::Instance()->getDrivers()) 0058 { 0059 if (di->getClientState() && di->getPort() == port) 0060 stopDrivers.append(di); 0061 } 0062 0063 if (stopDrivers.isEmpty()) 0064 { 0065 qCWarning(KSTARS) << "Could not find devices on port " << port; 0066 return false; 0067 } 0068 0069 DriverManager::Instance()->stopDevices(stopDrivers); 0070 0071 for (auto &di : stopDrivers) 0072 DriverManager::Instance()->removeDriver(di); 0073 0074 return true; 0075 } 0076 0077 bool INDIDBus::connect(const QString &host, int port) 0078 { 0079 QSharedPointer<DriverInfo> remote_indi(new DriverInfo(QString("INDI Remote Host"))); 0080 0081 remote_indi->setHostParameters(host, port); 0082 0083 remote_indi->setDriverSource(GENERATED_SOURCE); 0084 0085 // TODO migrate to event-based system. 0086 DriverManager::Instance()->connectRemoteHost(remote_indi); 0087 // { 0088 // delete (remote_indi); 0089 // remote_indi = nullptr; 0090 // return false; 0091 // } 0092 0093 DriverManager::Instance()->addDriver(remote_indi); 0094 0095 return true; 0096 } 0097 0098 bool INDIDBus::disconnect(const QString &host, int port) 0099 { 0100 for (auto &dv : DriverManager::Instance()->getDrivers()) 0101 { 0102 if (dv->getHost() == host && dv->getPort() == port && dv->getDriverSource() == GENERATED_SOURCE) 0103 { 0104 if (DriverManager::Instance()->disconnectRemoteHost(dv)) 0105 { 0106 DriverManager::Instance()->removeDriver(dv); 0107 return true; 0108 } 0109 else 0110 return false; 0111 } 0112 } 0113 0114 return false; 0115 } 0116 0117 QStringList INDIDBus::getDevices() 0118 { 0119 QStringList devices; 0120 0121 for (auto &oneDevice : INDIListener::devices()) 0122 { 0123 devices << oneDevice->getDeviceName(); 0124 } 0125 0126 return devices; 0127 } 0128 0129 QStringList INDIDBus::getDevicesPaths(uint32_t interface) 0130 { 0131 QStringList paths; 0132 for (auto &oneDevice : INDIListener::devicesByInterface(interface)) 0133 { 0134 QSharedPointer<ISD::ConcreteDevice> concreteDevice; 0135 if (oneDevice->findConcreteDevice(interface, concreteDevice)) 0136 paths << concreteDevice->getDUBSObjectPath(); 0137 } 0138 return paths; 0139 } 0140 0141 QStringList INDIDBus::getProperties(const QString &device) 0142 { 0143 QStringList properties; 0144 0145 for (auto &oneDevice : INDIListener::devices()) 0146 { 0147 if (oneDevice->getDeviceName() == device) 0148 { 0149 // Let's print a list of all device properties 0150 for (const auto &prop : oneDevice->getProperties()) 0151 { 0152 switch (prop.getType()) 0153 { 0154 case INDI_SWITCH: 0155 for (const auto &it : *prop.getSwitch()) 0156 properties << device + '.' + QString(prop.getName()) + '.' + it.getName(); 0157 break; 0158 0159 case INDI_TEXT: 0160 for (const auto &it : *prop.getText()) 0161 properties << device + '.' + QString(prop.getName()) + '.' + it.getName(); 0162 break; 0163 0164 case INDI_NUMBER: 0165 for (const auto &it : *prop.getNumber()) 0166 properties << device + '.' + QString(prop.getName()) + '.' + it.getName(); 0167 break; 0168 0169 case INDI_LIGHT: 0170 for (const auto &it : *prop.getLight()) 0171 properties << device + '.' + QString(prop.getName()) + '.' + it.getName(); 0172 break; 0173 0174 case INDI_BLOB: 0175 for (const auto &it : *prop.getBLOB()) 0176 properties << device + '.' + QString(prop.getName()) + '.' + it.getName(); 0177 break; 0178 0179 case INDI_UNKNOWN: 0180 qCWarning(KSTARS) << device << '.' << QString(prop.getName()) << " has an unknown type! Aborting..."; 0181 return properties; 0182 } 0183 } 0184 0185 return properties; 0186 } 0187 } 0188 0189 qCWarning(KSTARS) << "Could not find device: " << device; 0190 return properties; 0191 } 0192 0193 QString INDIDBus::getPropertyState(const QString &device, const QString &property) 0194 { 0195 QString status = "Invalid"; 0196 0197 for (auto &oneDevice : INDIListener::devices()) 0198 { 0199 if (oneDevice->getDeviceName() == device) 0200 { 0201 auto prop = oneDevice->getProperty(property.toLatin1()); 0202 if (prop) 0203 { 0204 status = QString(pstateStr(prop.getState())); 0205 return status; 0206 } 0207 0208 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0209 return status; 0210 } 0211 } 0212 0213 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0214 return status; 0215 } 0216 0217 bool INDIDBus::sendProperty(const QString &device, const QString &property) 0218 { 0219 for (auto &oneDevice : INDIListener::devices()) 0220 { 0221 ClientManager *cm = oneDevice->getDeviceInfo()->getDriverInfo()->getClientManager(); 0222 0223 if (oneDevice->getDeviceName() == device) 0224 { 0225 auto prop = oneDevice->getProperty(property.toLatin1()); 0226 if (prop) 0227 { 0228 switch (prop.getType()) 0229 { 0230 case INDI_SWITCH: 0231 prop.getSwitch()->setState(IPS_BUSY); 0232 cm->sendNewProperty(prop.getSwitch()); 0233 break; 0234 0235 case INDI_TEXT: 0236 prop.getText()->setState(IPS_BUSY); 0237 cm->sendNewProperty(prop.getText()); 0238 break; 0239 0240 case INDI_NUMBER: 0241 prop.getNumber()->setState(IPS_BUSY); 0242 cm->sendNewProperty(prop.getNumber()); 0243 break; 0244 0245 default: 0246 qCWarning(KSTARS) << "Only switch, text, and number properties are supported."; 0247 return false; 0248 } 0249 0250 return true; 0251 } 0252 0253 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0254 return false; 0255 } 0256 } 0257 0258 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0259 return false; 0260 } 0261 0262 QString INDIDBus::getLight(const QString &device, const QString &property, const QString &lightName) 0263 { 0264 QString status = "Invalid"; 0265 0266 for (auto &oneDevice : INDIListener::devices()) 0267 { 0268 if (oneDevice->getDeviceName() == device) 0269 { 0270 auto prop = oneDevice->getProperty(property.toLatin1()); 0271 if (prop) 0272 { 0273 auto lp = prop.getLight(); 0274 if (lp) 0275 { 0276 auto l = lp->findWidgetByName(lightName.toLatin1()); 0277 if (l) 0278 { 0279 status = QString(l->getStateAsString()); 0280 return status; 0281 } 0282 } 0283 } 0284 0285 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0286 return status; 0287 } 0288 } 0289 0290 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property; 0291 return status; 0292 } 0293 0294 bool INDIDBus::setSwitch(const QString &device, const QString &property, const QString &switchName, 0295 const QString &status) 0296 { 0297 if (status != "On" && status != "Off") 0298 { 0299 qCWarning(KSTARS) << "Invalid switch status requested: " << status; 0300 return false; 0301 } 0302 0303 for (auto &oneDevice : INDIListener::devices()) 0304 { 0305 if (oneDevice->getDeviceName() == device) 0306 { 0307 auto sp = oneDevice->getBaseDevice().getSwitch(property.toLatin1()); 0308 0309 if (sp.getRule() == ISR_1OFMANY && status == "Off") 0310 { 0311 qCWarning(KSTARS) << "Cannot set ISR_1OFMANY switch to Off. At least one switch must be On."; 0312 return false; 0313 } 0314 0315 if (sp.getRule() == ISR_1OFMANY || sp.getRule() == ISR_ATMOST1) 0316 sp.reset(); 0317 0318 auto sw = sp.findWidgetByName(switchName.toLatin1()); 0319 0320 if (sw) 0321 { 0322 sw->setState(status == "On" ? ISS_ON : ISS_OFF); 0323 return true; 0324 } 0325 0326 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName; 0327 return false; 0328 } 0329 } 0330 0331 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName; 0332 return false; 0333 } 0334 0335 QString INDIDBus::getSwitch(const QString &device, const QString &property, const QString &switchName) 0336 { 0337 QString result("Invalid"); 0338 0339 for (auto &oneDevice : INDIListener::devices()) 0340 { 0341 if (oneDevice->getDeviceName() == device) 0342 { 0343 auto sp = oneDevice->getBaseDevice().getSwitch(property.toLatin1()); 0344 if (sp) 0345 { 0346 auto sw = sp.findWidgetByName(switchName.toLatin1()); 0347 if (sw) 0348 { 0349 result = ((sw->getState() == ISS_ON) ? "On" : "Off"); 0350 return result; 0351 } 0352 0353 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName; 0354 return result; 0355 } 0356 0357 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName; 0358 return result; 0359 } 0360 } 0361 0362 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName; 0363 return result; 0364 } 0365 0366 bool INDIDBus::setText(const QString &device, const QString &property, const QString &textName, const QString &text) 0367 { 0368 for (auto &oneDevice : INDIListener::devices()) 0369 { 0370 if (oneDevice->getDeviceName() == device) 0371 { 0372 auto tp = oneDevice->getBaseDevice().getText(property.toLatin1()); 0373 0374 if (tp) 0375 { 0376 auto t = tp.findWidgetByName(textName.toLatin1()); 0377 if (t) 0378 { 0379 t->setText(text.toLatin1()); 0380 return true; 0381 } 0382 0383 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0384 return false; 0385 } 0386 0387 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0388 return false; 0389 } 0390 } 0391 0392 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0393 return false; 0394 } 0395 0396 QString INDIDBus::getText(const QString &device, const QString &property, const QString &textName) 0397 { 0398 QString result("Invalid"); 0399 0400 for (auto &oneDevice : INDIListener::devices()) 0401 { 0402 if (oneDevice->getDeviceName() == device) 0403 { 0404 auto tp = oneDevice->getBaseDevice().getText(property.toLatin1()); 0405 if (tp) 0406 { 0407 auto t = tp.findWidgetByName(textName.toLatin1()); 0408 if (t) 0409 { 0410 result = QString(t->getText()); 0411 return result; 0412 } 0413 0414 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0415 return result; 0416 } 0417 0418 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0419 return result; 0420 } 0421 } 0422 0423 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName; 0424 return result; 0425 } 0426 0427 bool INDIDBus::setNumber(const QString &device, const QString &property, const QString &numberName, double value) 0428 { 0429 for (auto &oneDevice : INDIListener::devices()) 0430 { 0431 if (oneDevice->getDeviceName() == device) 0432 { 0433 auto np = oneDevice->getBaseDevice().getNumber(property.toLatin1()); 0434 0435 if (np) 0436 { 0437 auto n = np.findWidgetByName(numberName.toLatin1()); 0438 if (n) 0439 { 0440 n->setValue(value); 0441 return true; 0442 } 0443 0444 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0445 return false; 0446 } 0447 0448 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0449 return false; 0450 } 0451 } 0452 0453 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0454 return false; 0455 } 0456 0457 double INDIDBus::getNumber(const QString &device, const QString &property, const QString &numberName) 0458 { 0459 double result = NaN::d; 0460 0461 for (auto &oneDevice : INDIListener::devices()) 0462 { 0463 if (oneDevice->getDeviceName() == device) 0464 { 0465 auto np = oneDevice->getBaseDevice().getNumber(property.toLatin1()); 0466 if (np) 0467 { 0468 auto n = np.findWidgetByName(numberName.toLatin1()); 0469 if (n) 0470 { 0471 result = n->getValue(); 0472 return result; 0473 } 0474 0475 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0476 return result; 0477 } 0478 0479 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0480 return result; 0481 } 0482 } 0483 0484 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName; 0485 return result; 0486 } 0487 0488 QByteArray INDIDBus::getBLOBData(const QString &device, const QString &property, const QString &blobName, 0489 QString &blobFormat, int &size) 0490 { 0491 QByteArray array; 0492 size = -1; 0493 0494 for (auto &oneDevice : INDIListener::devices()) 0495 { 0496 if (oneDevice->getDeviceName() == device) 0497 { 0498 auto bp = oneDevice->getBaseDevice().getBLOB(property.toLatin1()); 0499 if (bp) 0500 { 0501 auto b = bp.findWidgetByName(blobName.toLatin1()); 0502 if (b) 0503 { 0504 const char *rawData = static_cast<const char *>(b->getBlob()); 0505 array = QByteArray::fromRawData(rawData, b->getSize()); 0506 size = b->getBlobLen(); 0507 blobFormat = QString(b->getFormat()).trimmed(); 0508 0509 return array; 0510 } 0511 0512 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0513 return array; 0514 } 0515 0516 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0517 return array; 0518 } 0519 } 0520 0521 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0522 return array; 0523 } 0524 0525 QString INDIDBus::getBLOBFile(const QString &device, const QString &property, const QString &blobName, 0526 QString &blobFormat, int &size) 0527 { 0528 QString filename; 0529 size = -1; 0530 0531 for (auto &oneDevice : INDIListener::devices()) 0532 { 0533 if (oneDevice->getDeviceName() == device) 0534 { 0535 auto bp = oneDevice->getBaseDevice().getBLOB(property.toLatin1()); 0536 if (bp) 0537 { 0538 auto b = bp.findWidgetByName(blobName.toLatin1()); 0539 if (b) 0540 { 0541 filename = QString(static_cast<char *>(b->aux2)); 0542 size = b->bloblen; 0543 blobFormat = QString(b->format).trimmed(); 0544 0545 return filename; 0546 } 0547 0548 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0549 return filename; 0550 } 0551 0552 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0553 return filename; 0554 } 0555 } 0556 0557 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName; 0558 return filename; 0559 }