Kstars

indidbus.cpp
1/*
2 SPDX-FileCopyrightText: 2014 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "indidbus.h"
8
9#include "indiadaptor.h"
10#include "nan.h"
11#include "indi/drivermanager.h"
12#include "indi/driverinfo.h"
13#include "indi/clientmanager.h"
14#include "indi/indilistener.h"
15#include "indi/indiconcretedevice.h"
16#include "indi/deviceinfo.h"
17
18#include "kstars_debug.h"
19
20#include <basedevice.h>
21
22INDIDBus::INDIDBus(QObject *parent) : QObject(parent)
23{
24 new INDIAdaptor(this);
25 QDBusConnection::sessionBus().registerObject("/KStars/INDI", this);
26}
27
28bool INDIDBus::start(int port, const QStringList &drivers)
29{
31
32 for (auto &driver : drivers)
33 {
34 auto drv = DriverManager::Instance()->findDriverByExec(driver);
35
36 if (drv == nullptr)
37 continue;
38
39 QSharedPointer<DriverInfo> di(new DriverInfo(QString("%1").arg(driver)));
40 di->setHostParameters("localhost", port);
41 di->setDriverSource(EM_XML);
42 di->setExecutable(driver);
43 di->setUniqueLabel(drv->getUniqueLabel().isEmpty() ? drv->getLabel() : drv->getUniqueLabel());
44
45 DriverManager::Instance()->addDriver(di);
46 newDrivers.append(di);
47 }
48
49 DriverManager::Instance()->startDevices(newDrivers);
50 return true;
51}
52
53bool INDIDBus::stop(const QString &port)
54{
56
57 foreach (QSharedPointer<DriverInfo>di, DriverManager::Instance()->getDrivers())
58 {
59 if (di->getClientState() && di->getPort() == port)
60 stopDrivers.append(di);
61 }
62
63 if (stopDrivers.isEmpty())
64 {
65 qCWarning(KSTARS) << "Could not find devices on port " << port;
66 return false;
67 }
68
69 DriverManager::Instance()->stopDevices(stopDrivers);
70
71 for (auto &di : stopDrivers)
72 DriverManager::Instance()->removeDriver(di);
73
74 return true;
75}
76
77bool INDIDBus::connect(const QString &host, int port)
78{
80
81 remote_indi->setHostParameters(host, port);
82
83 remote_indi->setDriverSource(GENERATED_SOURCE);
84
85 // TODO migrate to event-based system.
86 DriverManager::Instance()->connectRemoteHost(remote_indi);
87 // {
88 // delete (remote_indi);
89 // remote_indi = nullptr;
90 // return false;
91 // }
92
93 DriverManager::Instance()->addDriver(remote_indi);
94
95 return true;
96}
97
98bool INDIDBus::disconnect(const QString &host, int port)
99{
100 for (auto &dv : DriverManager::Instance()->getDrivers())
101 {
102 if (dv->getHost() == host && dv->getPort() == port && dv->getDriverSource() == GENERATED_SOURCE)
103 {
104 if (DriverManager::Instance()->disconnectRemoteHost(dv))
105 {
106 DriverManager::Instance()->removeDriver(dv);
107 return true;
108 }
109 else
110 return false;
111 }
112 }
113
114 return false;
115}
116
118{
119 QStringList devices;
120
121 for (auto &oneDevice : INDIListener::devices())
122 {
123 devices << oneDevice->getDeviceName();
124 }
125
126 return devices;
127}
128
130{
131 QStringList paths;
132 for (auto &oneDevice : INDIListener::devicesByInterface(interface))
133 {
135 if (oneDevice->findConcreteDevice(interface, concreteDevice))
136 paths << concreteDevice->getDUBSObjectPath();
137 }
138 return paths;
139}
140
142{
143 QStringList properties;
144
145 for (auto &oneDevice : INDIListener::devices())
146 {
147 if (oneDevice->getDeviceName() == device)
148 {
149 // Let's print a list of all device properties
150 for (const auto &prop : oneDevice->getProperties())
151 {
152 switch (prop.getType())
153 {
154 case INDI_SWITCH:
155 for (const auto &it : *prop.getSwitch())
156 properties << device + '.' + QString(prop.getName()) + '.' + it.getName();
157 break;
158
159 case INDI_TEXT:
160 for (const auto &it : *prop.getText())
161 properties << device + '.' + QString(prop.getName()) + '.' + it.getName();
162 break;
163
164 case INDI_NUMBER:
165 for (const auto &it : *prop.getNumber())
166 properties << device + '.' + QString(prop.getName()) + '.' + it.getName();
167 break;
168
169 case INDI_LIGHT:
170 for (const auto &it : *prop.getLight())
171 properties << device + '.' + QString(prop.getName()) + '.' + it.getName();
172 break;
173
174 case INDI_BLOB:
175 for (const auto &it : *prop.getBLOB())
176 properties << device + '.' + QString(prop.getName()) + '.' + it.getName();
177 break;
178
179 case INDI_UNKNOWN:
180 qCWarning(KSTARS) << device << '.' << QString(prop.getName()) << " has an unknown type! Aborting...";
181 return properties;
182 }
183 }
184
185 return properties;
186 }
187 }
188
189 qCWarning(KSTARS) << "Could not find device: " << device;
190 return properties;
191}
192
193QString INDIDBus::getPropertyState(const QString &device, const QString &property)
194{
195 QString status = "Invalid";
196
197 for (auto &oneDevice : INDIListener::devices())
198 {
199 if (oneDevice->getDeviceName() == device)
200 {
201 auto prop = oneDevice->getProperty(property.toLatin1());
202 if (prop)
203 {
204 status = QString(pstateStr(prop.getState()));
205 return status;
206 }
207
208 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
209 return status;
210 }
211 }
212
213 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
214 return status;
215}
216
217bool INDIDBus::sendProperty(const QString &device, const QString &property)
218{
219 for (auto &oneDevice : INDIListener::devices())
220 {
221 ClientManager *cm = oneDevice->getDeviceInfo()->getDriverInfo()->getClientManager();
222
223 if (oneDevice->getDeviceName() == device)
224 {
225 auto prop = oneDevice->getProperty(property.toLatin1());
226 if (prop)
227 {
228 switch (prop.getType())
229 {
230 case INDI_SWITCH:
231 prop.getSwitch()->setState(IPS_BUSY);
232 cm->sendNewProperty(prop.getSwitch());
233 break;
234
235 case INDI_TEXT:
236 prop.getText()->setState(IPS_BUSY);
237 cm->sendNewProperty(prop.getText());
238 break;
239
240 case INDI_NUMBER:
241 prop.getNumber()->setState(IPS_BUSY);
242 cm->sendNewProperty(prop.getNumber());
243 break;
244
245 default:
246 qCWarning(KSTARS) << "Only switch, text, and number properties are supported.";
247 return false;
248 }
249
250 return true;
251 }
252
253 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
254 return false;
255 }
256 }
257
258 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
259 return false;
260}
261
262QString INDIDBus::getLight(const QString &device, const QString &property, const QString &lightName)
263{
264 QString status = "Invalid";
265
266 for (auto &oneDevice : INDIListener::devices())
267 {
268 if (oneDevice->getDeviceName() == device)
269 {
270 auto prop = oneDevice->getProperty(property.toLatin1());
271 if (prop)
272 {
273 auto lp = prop.getLight();
274 if (lp)
275 {
276 auto l = lp->findWidgetByName(lightName.toLatin1());
277 if (l)
278 {
279 status = QString(l->getStateAsString());
280 return status;
281 }
282 }
283 }
284
285 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
286 return status;
287 }
288 }
289
290 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property;
291 return status;
292}
293
294bool INDIDBus::setSwitch(const QString &device, const QString &property, const QString &switchName,
295 const QString &status)
296{
297 if (status != "On" && status != "Off")
298 {
299 qCWarning(KSTARS) << "Invalid switch status requested: " << status;
300 return false;
301 }
302
303 for (auto &oneDevice : INDIListener::devices())
304 {
305 if (oneDevice->getDeviceName() == device)
306 {
307 auto sp = oneDevice->getBaseDevice().getSwitch(property.toLatin1());
308
309 if (sp.getRule() == ISR_1OFMANY && status == "Off")
310 {
311 qCWarning(KSTARS) << "Cannot set ISR_1OFMANY switch to Off. At least one switch must be On.";
312 return false;
313 }
314
315 if (sp.getRule() == ISR_1OFMANY || sp.getRule() == ISR_ATMOST1)
316 sp.reset();
317
318 auto sw = sp.findWidgetByName(switchName.toLatin1());
319
320 if (sw)
321 {
322 sw->setState(status == "On" ? ISS_ON : ISS_OFF);
323 return true;
324 }
325
326 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName;
327 return false;
328 }
329 }
330
331 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName;
332 return false;
333}
334
335QString INDIDBus::getSwitch(const QString &device, const QString &property, const QString &switchName)
336{
337 QString result("Invalid");
338
339 for (auto &oneDevice : INDIListener::devices())
340 {
341 if (oneDevice->getDeviceName() == device)
342 {
343 auto sp = oneDevice->getBaseDevice().getSwitch(property.toLatin1());
344 if (sp)
345 {
346 auto sw = sp.findWidgetByName(switchName.toLatin1());
347 if (sw)
348 {
349 result = ((sw->getState() == ISS_ON) ? "On" : "Off");
350 return result;
351 }
352
353 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName;
354 return result;
355 }
356
357 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName;
358 return result;
359 }
360 }
361
362 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << switchName;
363 return result;
364}
365
366bool INDIDBus::setText(const QString &device, const QString &property, const QString &textName, const QString &text)
367{
368 for (auto &oneDevice : INDIListener::devices())
369 {
370 if (oneDevice->getDeviceName() == device)
371 {
372 auto tp = oneDevice->getBaseDevice().getText(property.toLatin1());
373
374 if (tp)
375 {
376 auto t = tp.findWidgetByName(textName.toLatin1());
377 if (t)
378 {
379 t->setText(text.toLatin1());
380 return true;
381 }
382
383 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
384 return false;
385 }
386
387 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
388 return false;
389 }
390 }
391
392 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
393 return false;
394}
395
396QString INDIDBus::getText(const QString &device, const QString &property, const QString &textName)
397{
398 QString result("Invalid");
399
400 for (auto &oneDevice : INDIListener::devices())
401 {
402 if (oneDevice->getDeviceName() == device)
403 {
404 auto tp = oneDevice->getBaseDevice().getText(property.toLatin1());
405 if (tp)
406 {
407 auto t = tp.findWidgetByName(textName.toLatin1());
408 if (t)
409 {
410 result = QString(t->getText());
411 return result;
412 }
413
414 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
415 return result;
416 }
417
418 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
419 return result;
420 }
421 }
422
423 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << textName;
424 return result;
425}
426
427bool INDIDBus::setNumber(const QString &device, const QString &property, const QString &numberName, double value)
428{
429 for (auto &oneDevice : INDIListener::devices())
430 {
431 if (oneDevice->getDeviceName() == device)
432 {
433 auto np = oneDevice->getBaseDevice().getNumber(property.toLatin1());
434
435 if (np)
436 {
437 auto n = np.findWidgetByName(numberName.toLatin1());
438 if (n)
439 {
440 n->setValue(value);
441 return true;
442 }
443
444 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
445 return false;
446 }
447
448 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
449 return false;
450 }
451 }
452
453 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
454 return false;
455}
456
457double INDIDBus::getNumber(const QString &device, const QString &property, const QString &numberName)
458{
459 double result = NaN::d;
460
461 for (auto &oneDevice : INDIListener::devices())
462 {
463 if (oneDevice->getDeviceName() == device)
464 {
465 auto np = oneDevice->getBaseDevice().getNumber(property.toLatin1());
466 if (np)
467 {
468 auto n = np.findWidgetByName(numberName.toLatin1());
469 if (n)
470 {
471 result = n->getValue();
472 return result;
473 }
474
475 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
476 return result;
477 }
478
479 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
480 return result;
481 }
482 }
483
484 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << numberName;
485 return result;
486}
487
488QByteArray INDIDBus::getBLOBData(const QString &device, const QString &property, const QString &blobName,
489 QString &blobFormat, int &size)
490{
491 QByteArray array;
492 size = -1;
493
494 for (auto &oneDevice : INDIListener::devices())
495 {
496 if (oneDevice->getDeviceName() == device)
497 {
498 auto bp = oneDevice->getBaseDevice().getBLOB(property.toLatin1());
499 if (bp)
500 {
501 auto b = bp.findWidgetByName(blobName.toLatin1());
502 if (b)
503 {
504 const char *rawData = static_cast<const char *>(b->getBlob());
505 array = QByteArray::fromRawData(rawData, b->getSize());
506 size = b->getBlobLen();
507 blobFormat = QString(b->getFormat()).trimmed();
508
509 return array;
510 }
511
512 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
513 return array;
514 }
515
516 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
517 return array;
518 }
519 }
520
521 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
522 return array;
523}
524
525QString INDIDBus::getBLOBFile(const QString &device, const QString &property, const QString &blobName,
526 QString &blobFormat, int &size)
527{
528 QString filename;
529 size = -1;
530
531 for (auto &oneDevice : INDIListener::devices())
532 {
533 if (oneDevice->getDeviceName() == device)
534 {
535 auto bp = oneDevice->getBaseDevice().getBLOB(property.toLatin1());
536 if (bp)
537 {
538 auto b = bp.findWidgetByName(blobName.toLatin1());
539 if (b)
540 {
541 filename = QString(static_cast<char *>(b->aux2));
542 size = b->bloblen;
543 blobFormat = QString(b->format).trimmed();
544
545 return filename;
546 }
547
548 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
549 return filename;
550 }
551
552 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
553 return filename;
554 }
555 }
556
557 qCWarning(KSTARS) << "Could not find property: " << device << '.' << property << '.' << blobName;
558 return filename;
559}
ClientManager manages connection to INDI server, creation of devices, and receiving/sending propertie...
DriverInfo holds all metadata associated with a particular INDI driver.
Definition driverinfo.h:46
Q_SCRIPTABLE bool setSwitch(const QString &device, const QString &property, const QString &switchName, const QString &status)
DBUS interface function.
Definition indidbus.cpp:294
Q_SCRIPTABLE bool setText(const QString &device, const QString &property, const QString &textName, const QString &text)
DBUS interface function.
Definition indidbus.cpp:366
Q_SCRIPTABLE QString getText(const QString &device, const QString &property, const QString &textName)
DBUS interface function.
Definition indidbus.cpp:396
Q_SCRIPTABLE bool sendProperty(const QString &device, const QString &property)
DBUS interface function.
Definition indidbus.cpp:217
Q_SCRIPTABLE QByteArray getBLOBData(const QString &device, const QString &property, const QString &blobName, QString &blobFormat, int &size)
DBUS interface function.
Definition indidbus.cpp:488
Q_SCRIPTABLE double getNumber(const QString &device, const QString &property, const QString &numberName)
DBUS interface function.
Definition indidbus.cpp:457
Q_SCRIPTABLE QString getBLOBFile(const QString &device, const QString &property, const QString &blobName, QString &blobFormat, int &size)
DBUS interface function.
Definition indidbus.cpp:525
Q_SCRIPTABLE QStringList getDevicesPaths(uint32_t interface)
DBUS interface function.
Definition indidbus.cpp:129
Q_SCRIPTABLE QString getPropertyState(const QString &device, const QString &property)
DBUS interface function.
Definition indidbus.cpp:193
Q_SCRIPTABLE QStringList getProperties(const QString &device)
DBUS interface function.
Definition indidbus.cpp:141
Q_SCRIPTABLE QString getSwitch(const QString &device, const QString &property, const QString &switchName)
DBUS interface function.
Definition indidbus.cpp:335
Q_SCRIPTABLE bool setNumber(const QString &device, const QString &property, const QString &numberName, double value)
DBUS interface function.
Definition indidbus.cpp:427
Q_SCRIPTABLE bool connect(const QString &host, int port)
DBUS interface function.
Definition indidbus.cpp:77
Q_SCRIPTABLE bool stop(const QString &port)
DBUS interface function.
Definition indidbus.cpp:53
Q_SCRIPTABLE QString getLight(const QString &device, const QString &property, const QString &lightName)
DBUS interface function.
Definition indidbus.cpp:262
Q_SCRIPTABLE bool start(int port, const QStringList &drivers)
DBUS interface function.
Definition indidbus.cpp:28
Q_SCRIPTABLE QStringList getDevices()
DBUS interface function.
Definition indidbus.cpp:117
Q_SCRIPTABLE bool disconnect(const QString &host, int port)
DBUS interface function.
Definition indidbus.cpp:98
QByteArray fromRawData(const char *data, qsizetype size)
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
QVariant property(const char *name) const const
QByteArray toLatin1() const const
QString trimmed() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.