Kstars

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

KDE's Doxygen guidelines are available online.