Kstars

indilistener.cpp
1 /*
2  SPDX-FileCopyrightText: 2012 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 
6  Handle INDI Standard properties.
7 */
8 
9 #include "indilistener.h"
10 
11 #include "clientmanager.h"
12 #include "deviceinfo.h"
13 #include "kstars.h"
14 #include "Options.h"
15 
16 #include "auxiliary/ksnotification.h"
17 
18 #include <knotification.h>
19 
20 #include <basedevice.h>
21 #include <indi_debug.h>
22 
23 INDIListener *INDIListener::_INDIListener = nullptr;
24 
25 INDIListener *INDIListener::Instance()
26 {
27  if (_INDIListener == nullptr)
28  {
29  _INDIListener = new INDIListener(KStars::Instance());
30 
31  // connect(_INDIListener, &INDIListener::newTelescope,
32  // [&]()
33  // {
34  // KStars::Instance()->slotSetTelescopeEnabled(true);
35  // });
36 
37  // connect(_INDIListener, &INDIListener::newDome,
38  // [&]()
39  // {
40  // KStars::Instance()->slotSetDomeEnabled(true);
41  // });
42  }
43 
44  return _INDIListener;
45 }
46 
47 INDIListener::INDIListener(QObject *parent) : QObject(parent) {}
48 
49 INDIListener::~INDIListener()
50 {
51  qDeleteAll(devices);
52 }
53 
54 ISD::GenericDevice *INDIListener::getDevice(const QString &name) const
55 {
56  for (auto &oneDevice : devices)
57  {
58  if (oneDevice->getDeviceName() == name)
59  return oneDevice;
60  }
61  return nullptr;
62 }
63 
64 void INDIListener::addClient(ClientManager *cm)
65 {
66  qCDebug(KSTARS_INDI)
67  << "INDIListener: Adding a new client manager to INDI listener..";
68 
69  clients.append(cm);
70 
71  connect(cm, &ClientManager::newINDIDevice, this, &INDIListener::processDevice);
72  connect(cm, &ClientManager::newINDIProperty, this, &INDIListener::registerProperty);
73 
74  connect(cm, &ClientManager::removeINDIDevice, this, &INDIListener::removeDevice);
75  connect(cm, &ClientManager::removeINDIProperty, this, &INDIListener::removeProperty);
76 
77  connect(cm, &ClientManager::newINDISwitch, this, &INDIListener::processSwitch);
78  connect(cm, &ClientManager::newINDIText, this, &INDIListener::processText);
79  connect(cm, &ClientManager::newINDINumber, this, &INDIListener::processNumber);
80  connect(cm, &ClientManager::newINDILight, this, &INDIListener::processLight);
81  connect(cm, &ClientManager::newINDIBLOB, this, &INDIListener::processBLOB);
82  connect(cm, &ClientManager::newINDIUniversalMessage, this,
83  &INDIListener::processUniversalMessage);
84 }
85 
86 void INDIListener::removeClient(ClientManager *cm)
87 {
88  qCDebug(KSTARS_INDI) << "INDIListener: Removing client manager for server"
89  << cm->getHost() << "@" << cm->getPort();
90 
92  clients.removeOne(cm);
93 
94  while (it != devices.end())
95  {
96  DriverInfo *dv = (*it)->getDriverInfo();
97  bool hostSource = (dv->getDriverSource() == HOST_SOURCE) ||
98  (dv->getDriverSource() == GENERATED_SOURCE);
99 
100  if (cm->isDriverManaged(dv))
101  {
102  cm->removeManagedDriver(dv);
103  cm->disconnect(this);
104  if (hostSource)
105  return;
106  }
107  else
108  ++it;
109  }
110 }
111 
112 void INDIListener::processDevice(DeviceInfo *dv)
113 {
114  ClientManager *cm = qobject_cast<ClientManager *>(sender());
115  Q_ASSERT_X(cm, __FUNCTION__, "Client manager is not valid.");
116 
117  qCDebug(KSTARS_INDI) << "INDIListener: New device" << dv->getDeviceName();
118 
119  auto gd = new ISD::GenericDevice(*dv, cm);
120  devices.append(gd);
121 
122  emit newDevice(gd);
123 
124  // If already connected, we need to process all the properties as well
125  auto isConnected = gd->isConnected();
126  // Register all existing properties
127  for (auto &oneProperty : dv->getBaseDevice()->getProperties())
128  {
129  gd->registerProperty(oneProperty);
130  if (isConnected)
131  {
132  switch (oneProperty.getType())
133  {
134  case INDI_SWITCH:
135  gd->processSwitch(oneProperty.getSwitch());
136  break;
137  case INDI_NUMBER:
138  gd->processNumber(oneProperty.getNumber());
139  break;
140  case INDI_TEXT:
141  gd->processText(oneProperty.getText());
142  break;
143  case INDI_LIGHT:
144  gd->processLight(oneProperty.getLight());
145  break;
146  default:
147  break;
148  }
149  }
150  }
151 }
152 
153 void INDIListener::removeDevice(const QString &deviceName)
154 {
155  qCDebug(KSTARS_INDI) << "INDIListener: Removing device" << deviceName;
156 
157  for (auto oneDevice : qAsConst(devices))
158  {
159  if (oneDevice->getDeviceName() == deviceName)
160  {
161  // Remove from list first
162  devices.removeOne(oneDevice);
163  // Then emit a signal to inform subscribers that this device is removed.
164  emit deviceRemoved(oneDevice);
165  // Delete this device later.
166  oneDevice->deleteLater();
167  return;
168  }
169  }
170 }
171 
172 void INDIListener::registerProperty(INDI::Property prop)
173 {
174  if (!prop.getRegistered())
175  return;
176 
177  qCDebug(KSTARS_INDI) << "<" << prop.getDeviceName() << ">: <" << prop.getName()
178  << ">";
179 
180  for (auto &oneDevice : devices)
181  {
182  if (oneDevice->getDeviceName() == prop.getDeviceName())
183  {
184  oneDevice->registerProperty(prop);
185  return;
186  }
187  }
188 }
189 
190 void INDIListener::removeProperty(const QString &device, const QString &name)
191 {
192  for (auto &oneDevice : devices)
193  {
194  if (oneDevice->getDeviceName() == device)
195  {
196  oneDevice->removeProperty(name);
197  return;
198  }
199  }
200 }
201 
202 void INDIListener::processSwitch(ISwitchVectorProperty *svp)
203 {
204  for (auto &oneDevice : devices)
205  {
206  if (oneDevice->getDeviceName() == svp->device)
207  {
208  oneDevice->processSwitch(svp);
209  break;
210  }
211  }
212 }
213 
214 void INDIListener::processNumber(INumberVectorProperty *nvp)
215 {
216  for (auto &oneDevice : devices)
217  {
218  if (oneDevice->getDeviceName() == nvp->device)
219  {
220  oneDevice->processNumber(nvp);
221  break;
222  }
223  }
224 }
225 
226 void INDIListener::processText(ITextVectorProperty *tvp)
227 {
228  for (auto &oneDevice : devices)
229  {
230  if (oneDevice->getDeviceName() == tvp->device)
231  {
232  oneDevice->processText(tvp);
233  break;
234  }
235  }
236 }
237 
238 void INDIListener::processLight(ILightVectorProperty *lvp)
239 {
240  for (auto &oneDevice : devices)
241  {
242  if (oneDevice->getDeviceName() == lvp->device)
243  {
244  oneDevice->processLight(lvp);
245  break;
246  }
247  }
248 }
249 
250 void INDIListener::processBLOB(IBLOB *bp)
251 {
252  for (auto &oneDevice : devices)
253  {
254  if (oneDevice->getDeviceName() == bp->bvp->device)
255  {
256  oneDevice->processBLOB(bp);
257  break;
258  }
259  }
260 }
261 
262 void INDIListener::processMessage(INDI::BaseDevice *dp, int messageID)
263 {
264  for (auto &oneDevice : devices)
265  {
266  if (oneDevice->getDeviceName() == dp->getDeviceName())
267  {
268  oneDevice->processMessage(messageID);
269  break;
270  }
271  }
272 }
273 
274 void INDIListener::processUniversalMessage(const QString &message)
275 {
276  QString displayMessage = message;
277  // Remove timestamp info as it is not suitable for message box
278  int colonIndex = displayMessage.indexOf(": ");
279  if (colonIndex > 0)
280  displayMessage = displayMessage.mid(colonIndex + 2);
281 
282  // Special case for Alignment since it is not tied to a device
283  if (displayMessage.startsWith("[ALIGNMENT]"))
284  {
285  qCDebug(KSTARS_INDI) << "AlignmentSubSystem:" << displayMessage;
286  return;
287  }
288 
289  if (Options::messageNotificationINDI())
290  {
291  KSNotification::event(QLatin1String("IndiServerMessage"), displayMessage,
292  KSNotification::EVENT_WARN);
293  }
294  else
295  {
296  KSNotification::transient(displayMessage, i18n("INDI Server Message"));
297  }
298 }
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void removeManagedDriver(DriverInfo *dv)
removeManagedDriver Remove managed driver from pool of drivers managed by this client manager.
static KStars * Instance()
Definition: kstars.h:125
QString i18n(const char *text, const TYPE &arg...)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QList::iterator begin()
QString mid(int position, int n) const const
QString message
void transient(const QString &message, const QString &title)
transient Non modal message box that gets deleted on close.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 19 2022 03:57:51 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.