Kstars

indilistener.cpp
1/*
2 SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
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
23INDIListener *INDIListener::_INDIListener = nullptr;
24
25INDIListener *INDIListener::Instance()
26{
27 if (_INDIListener == nullptr)
28 {
29 _INDIListener = new INDIListener(KStars::Instance());
30 qRegisterMetaType<INDI::BaseDevice>("INDI::BaseDevice");
31 }
32
33 return _INDIListener;
34}
35
36bool INDIListener::findDevice(const QString &name, QSharedPointer<ISD::GenericDevice> &device)
37{
38 auto all = devices();
39 auto it = std::find_if(all.begin(), all.end(), [name](auto & oneDevice)
40 {
41 return oneDevice->getDeviceName() == name;
42 });
43 if (it == all.end())
44 return false;
45
46 device = *it;
47 return true;
48}
49
50INDIListener::INDIListener(QObject *parent) : QObject(parent) {}
51
52bool INDIListener::getDevice(const QString &name, QSharedPointer<ISD::GenericDevice> &device) const
53{
54 for (auto &oneDevice : m_Devices)
55 {
56 if (oneDevice->getDeviceName() == name)
57 {
58 device = oneDevice;
59 return true;
60 }
61 }
62 return false;
63}
64
65void INDIListener::addClient(ClientManager *cm)
66{
67 qCDebug(KSTARS_INDI)
68 << "INDIListener: Adding a new client manager to INDI listener..";
69
70 clients.append(cm);
71
72 connect(cm, &ClientManager::newINDIDevice, this, &INDIListener::processDevice);
73 connect(cm, &ClientManager::removeINDIDevice, this, &INDIListener::removeDevice);
74
75 connect(cm, &ClientManager::newINDIProperty, this, &INDIListener::registerProperty);
76 connect(cm, &ClientManager::updateINDIProperty, this, &INDIListener::updateProperty);
77 connect(cm, &ClientManager::removeINDIProperty, this, &INDIListener::removeProperty);
78
79 connect(cm, &ClientManager::newINDIMessage, this,
80 &INDIListener::processMessage);
81 connect(cm, &ClientManager::newINDIUniversalMessage, this,
82 &INDIListener::processUniversalMessage);
83}
84
85void INDIListener::removeClient(ClientManager *cm)
86{
87 qCDebug(KSTARS_INDI) << "INDIListener: Removing client manager for server"
88 << cm->getHost() << "@" << cm->getPort();
89
90 cm->disconnect(this);
91 clients.removeOne(cm);
92
93 auto managedDrivers = cm->getManagedDrivers();
94 for (auto &oneDriverInfo : managedDrivers)
95 cm->removeManagedDriver(oneDriverInfo);
96}
97
98void INDIListener::processDevice(DeviceInfo *dv)
99{
101 Q_ASSERT_X(cm, __FUNCTION__, "Client manager is not valid.");
102
103 qCDebug(KSTARS_INDI) << "INDIListener: New device" << dv->getDeviceName();
104
106 gd.reset(new ISD::GenericDevice(*dv, cm, this));
107
108 auto isConnected = gd->isConnected();
109 // If already connected, we need to process all the properties as well
110 // Register all existing properties
111 for (auto &oneProperty : dv->getBaseDevice().getProperties())
112 {
113 gd->registerProperty(oneProperty);
114 if (isConnected)
115 {
116 switch (oneProperty.getType())
117 {
118 case INDI_SWITCH:
119 gd->processSwitch(oneProperty.getSwitch());
120 break;
121 case INDI_NUMBER:
122 gd->processNumber(oneProperty.getNumber());
123 break;
124 case INDI_TEXT:
125 gd->processText(oneProperty.getText());
126 break;
127 case INDI_LIGHT:
128 gd->processLight(oneProperty.getLight());
129 break;
130 default:
131 break;
132 }
133 }
134 }
135
136 m_Devices.append(std::move(gd));
137 emit newDevice(m_Devices.last());
138
139}
140
141void INDIListener::removeDevice(const QString &deviceName)
142{
143 qCDebug(KSTARS_INDI) << "INDIListener: Removing device" << deviceName;
144
145 for (auto oneDevice : std::as_const(m_Devices))
146 {
147 if (oneDevice->getDeviceName() == deviceName)
148 {
149 // Remove from list first
150 m_Devices.removeOne(oneDevice);
151 // Then emit a signal to inform subscribers that this device is removed.
152 emit deviceRemoved(oneDevice);
153 // Delete this device later.
154 oneDevice->deleteLater();
155 return;
156 }
157 }
158}
159
160void INDIListener::registerProperty(INDI::Property prop)
161{
162 if (!prop.getRegistered())
163 return;
164
165 qCDebug(KSTARS_INDI) << "<" << prop.getDeviceName() << ">: <" << prop.getName()
166 << ">";
167
168 for (auto &oneDevice : m_Devices)
169 {
170 if (oneDevice->getDeviceName() == prop.getDeviceName())
171 {
172 oneDevice->registerProperty(prop);
173 return;
174 }
175 }
176}
177
178void INDIListener::removeProperty(INDI::Property prop)
179{
180 for (auto &oneDevice : m_Devices)
181 {
182 if (oneDevice->getDeviceName() == prop.getDeviceName())
183 {
184 oneDevice->removeProperty(prop);
185 return;
186 }
187 }
188}
189
190void INDIListener::updateProperty(INDI::Property prop)
191{
192 for (auto &oneDevice : m_Devices)
193 {
194 if (oneDevice->getDeviceName() == prop.getDeviceName())
195 {
196 oneDevice->updateProperty(prop);
197 break;
198 }
199 }
200}
201
202void INDIListener::processMessage(INDI::BaseDevice dp, int messageID)
203{
204 for (auto &oneDevice : m_Devices)
205 {
206 if (oneDevice->getDeviceName() == dp.getDeviceName())
207 {
208 oneDevice->processMessage(messageID);
209 break;
210 }
211 }
212}
213
214void INDIListener::processUniversalMessage(const QString &message)
215{
216 QString displayMessage = message;
217 // Remove timestamp info as it is not suitable for message box
218 int colonIndex = displayMessage.indexOf(": ");
219 if (colonIndex > 0)
220 displayMessage = displayMessage.mid(colonIndex + 2);
221
222 // Special case for Alignment since it is not tied to a device
223 if (displayMessage.startsWith("[ALIGNMENT]"))
224 {
225 qCDebug(KSTARS_INDI) << "AlignmentSubSystem:" << displayMessage;
226 return;
227 }
228
229 if (Options::messageNotificationINDI())
230 {
231 KSNotification::event(QLatin1String("IndiServerMessage"), displayMessage,
232 KSNotification::INDI, KSNotification::Warn);
233 }
234 else
235 {
236 KSNotification::transient(displayMessage, i18n("INDI Server Message"));
237 }
238}
ClientManager manages connection to INDI server, creation of devices, and receiving/sending propertie...
void removeManagedDriver(const QSharedPointer< DriverInfo > &driver)
removeManagedDriver Remove managed driver from pool of drivers managed by this client manager.
DeviceInfo is simple class to hold DriverInfo and INDI::BaseDevice associated with a particular devic...
Definition deviceinfo.h:21
INDIListener is responsible for creating ISD::GDInterface generic devices as new devices arrive from ...
GenericDevice is the Generic Device for INDI devices.
Definition indistd.h:117
static KStars * Instance()
Definition kstars.h:121
QString i18n(const char *text, const TYPE &arg...)
void transient(const QString &message, const QString &title)
transient Non modal message box that gets deleted on close.
void append(QList< T > &&value)
bool removeOne(const AT &t)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
T qobject_cast(QObject *object)
QObject * sender() const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:04:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.