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/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 
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 {
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 
53 bool 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 
77 bool INDIDBus::connect(const QString &host, int port)
78 {
79  QSharedPointer<DriverInfo> remote_indi(new DriverInfo(QString("INDI Remote Host")));
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 
98 bool 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 
193 QString 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 
217 bool 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 
262 QString 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 
294 bool 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 
335 QString 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 
366 bool 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 
396 QString 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 
427 bool 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 
457 double 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 
488 QByteArray 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 
525 QString 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 }
void append(const T &value)
Q_SCRIPTABLE QStringList getDevicesPaths(uint32_t interface)
DBUS interface function.
Definition: indidbus.cpp:129
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:396
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:525
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:366
Q_SCRIPTABLE QStringList getProperties(const QString &device)
DBUS interface function.
Definition: indidbus.cpp:141
Q_SCRIPTABLE QStringList getDevices()
DBUS interface function.
Definition: indidbus.cpp:117
Q_SCRIPTABLE bool connect(const QString &host, int port)
DBUS interface function.
Definition: indidbus.cpp:77
QDBusConnection sessionBus()
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 sendProperty(const QString &device, const QString &property)
DBUS interface function.
Definition: indidbus.cpp:217
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:98
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:294
Q_SCRIPTABLE QString getSwitch(const QString &device, const QString &property, const QString &switchName)
DBUS interface function.
Definition: indidbus.cpp:335
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:488
Q_SCRIPTABLE QString getPropertyState(const QString &device, const QString &property)
DBUS interface function.
Definition: indidbus.cpp:193
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:457
Q_SCRIPTABLE QString getLight(const QString &device, const QString &property, const QString &lightName)
DBUS interface function.
Definition: indidbus.cpp:262
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Dec 7 2023 03:58:39 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.