Kstars

clientmanager.cpp
1/*
2 SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "clientmanager.h"
8
9#include "deviceinfo.h"
10#include "drivermanager.h"
11#include "guimanager.h"
12#include "indilistener.h"
13#include "Options.h"
14#include "servermanager.h"
15
16#include <indi_debug.h>
17#include <QTimer>
18
19ClientManager::ClientManager()
20{
21 connect(this, &ClientManager::newINDIProperty, this, &ClientManager::processNewProperty, Qt::UniqueConnection);
22 connect(this, &ClientManager::removeBLOBManager, this, &ClientManager::processRemoveBLOBManager, Qt::UniqueConnection);
23}
24
25bool ClientManager::isDriverManaged(const QSharedPointer<DriverInfo> &driver)
26{
27 return std::any_of(m_ManagedDrivers.begin(), m_ManagedDrivers.end(), [driver](const auto & oneDriver)
28 {
29 return driver == oneDriver;
30 });
31}
32
33void ClientManager::newDevice(INDI::BaseDevice dp)
34{
35 //setBLOBMode(B_ALSO, dp->getDeviceName());
36 // JM 2018.09.27: ClientManager will no longer handle BLOB, just messages.
37 // We relay the BLOB handling to BLOB Manager to better manage concurrent connections with large data
38 setBLOBMode(B_NEVER, dp.getDeviceName());
39
40 if (QString(dp.getDeviceName()).isEmpty())
41 {
42 qCWarning(KSTARS_INDI) << "Received invalid device with empty name! Ignoring the device...";
43 return;
44 }
45
46 qCDebug(KSTARS_INDI) << "Received new device" << dp.getDeviceName();
47
48 // First iteration find unique matches
49 for (auto &oneDriverInfo : m_ManagedDrivers)
50 {
51 if (oneDriverInfo->getUniqueLabel() == QString(dp.getDeviceName()))
52 {
53 oneDriverInfo->setUniqueLabel(dp.getDeviceName());
55 oneDriverInfo->addDevice(devInfo);
56 emit newINDIDevice(devInfo);
57 return;
58 }
59 }
60
61 // Second iteration find partial matches
62
63 for (auto &oneDriverInfo : m_ManagedDrivers)
64 {
65 auto dvName = oneDriverInfo->getName().split(' ').first();
66 if (dvName.isEmpty())
67 dvName = oneDriverInfo->getName();
68 if (/*dv->getUniqueLabel() == dp->getDeviceName() ||*/
69 QString(dp.getDeviceName()).startsWith(dvName, Qt::CaseInsensitive) ||
70 ((oneDriverInfo->getDriverSource() == HOST_SOURCE || oneDriverInfo->getDriverSource() == GENERATED_SOURCE)))
71 {
72 oneDriverInfo->setUniqueLabel(dp.getDeviceName());
74 oneDriverInfo->addDevice(devInfo);
75 emit newINDIDevice(devInfo);
76 return;
77 }
78 }
79}
80
81void ClientManager::newProperty(INDI::Property property)
82{
83 // Do not emit the signal if the server is disconnected or disconnecting (deadlock between signals)
84 if (!isServerConnected())
85 {
86 IDLog("Received new property %s for disconnected device %s, discarding\n", property.getName(), property.getDeviceName());
87 return;
88 }
89
90 //IDLog("Received new property %s for device %s\n", prop->getName(), prop->getgetDeviceName());
91 emit newINDIProperty(property);
92}
93
94void ClientManager::updateProperty(INDI::Property property)
95{
96 emit updateINDIProperty(property);
97}
98
99void ClientManager::removeProperty(INDI::Property prop)
100{
101 const QString name = prop.getName();
102 const QString device = prop.getDeviceName();
103 emit removeINDIProperty(prop);
104
105 // If BLOB property is removed, remove its corresponding property if one exists.
106 if (blobManagers.empty() == false && prop.getType() == INDI_BLOB && prop.getPermission() != IP_WO)
107 emit removeBLOBManager(device, name);
108}
109
110void ClientManager::processRemoveBLOBManager(const QString &device, const QString &property)
111{
112 auto manager = std::find_if(blobManagers.begin(), blobManagers.end(), [device, property](auto & oneManager)
113 {
114 const auto bProperty = oneManager->property("property").toString();
115 const auto bDevice = oneManager->property("device").toString();
116 return (device == bDevice && property == bProperty);
117 });
118
119 if (manager != blobManagers.end())
120 {
121 (*manager)->disconnectServer();
122 (*manager)->deleteLater();
123 blobManagers.removeOne(*manager);
124 }
125}
126
127void ClientManager::processNewProperty(INDI::Property prop)
128{
129 // Only handle RW and RO BLOB properties
130 if (prop.getType() == INDI_BLOB && prop.getPermission() != IP_WO)
131 {
132 BlobManager *bm = new BlobManager(this, getHost(), getPort(), prop.getDeviceName(), prop.getName());
133 connect(bm, &BlobManager::propertyUpdated, this, &ClientManager::updateINDIProperty);
134 connect(bm, &BlobManager::connected, this, [prop, this]()
135 {
136 if (prop && prop.getRegistered())
137 emit newBLOBManager(prop.getDeviceName(), prop);
138 });
139 blobManagers.append(bm);
140 }
141}
142
144{
145 disconnectServer();
146 for (auto &oneManager : blobManagers)
147 oneManager->disconnectServer();
148}
149
150void ClientManager::removeDevice(INDI::BaseDevice dp)
151{
152 QString deviceName = dp.getDeviceName();
153
155 while (it.hasNext())
156 {
157 auto &oneManager = it.next();
158 if (oneManager->property("device").toString() == deviceName)
159 {
160 oneManager->disconnect();
161 it.remove();
162 }
163 }
164
165 for (auto &driverInfo : m_ManagedDrivers)
166 {
167 for (auto &deviceInfo : driverInfo->getDevices())
168 {
169 if (deviceInfo->getDeviceName() == deviceName)
170 {
171 qCDebug(KSTARS_INDI) << "Removing device" << deviceName;
172
173 emit removeINDIDevice(deviceName);
174
175 driverInfo->removeDevice(deviceInfo);
176
177 if (driverInfo->isEmpty())
178 {
179 driverInfo->setClientState(false);
180 m_ManagedDrivers.removeOne(driverInfo);
181 }
182
183 return;
184 }
185 }
186 }
187}
188
189void ClientManager::newMessage(INDI::BaseDevice dp, int messageID)
190{
191 emit newINDIMessage(dp, messageID);
192}
193
194void ClientManager::newUniversalMessage(std::string message)
195{
196 emit newINDIUniversalMessage(QString::fromStdString(message));
197}
198
199
201{
202 qCDebug(KSTARS_INDI) << "Adding managed driver" << driver->getName();
203
204 m_ManagedDrivers.append(driver);
205
206 driver->setClientManager(this);
207
208 sManager = driver->getServerManager();
209}
210
212{
213 if (m_ManagedDrivers.empty())
214 {
215 qCDebug(KSTARS_INDI) << "removeManagedDriver: no managed drivers!";
216 return;
217 }
218
219 qCDebug(KSTARS_INDI) << "Removing managed driver" << driver->getName();
220
221 driver->setClientState(false);
222
223 for (auto &di : driver->getDevices())
224 {
225 // #1 Remove from GUI Manager
226 GUIManager::Instance()->removeDevice(di->getDeviceName());
227
228 // #2 Remove from INDI Listener
229 INDIListener::Instance()->removeDevice(di->getDeviceName());
230
231 // #3 Remove device from Driver Info
232 driver->removeDevice(di);
233 }
234 m_ManagedDrivers.removeOne(driver);
235}
236
237void ClientManager::serverConnected()
238{
239 qCDebug(KSTARS_INDI) << "INDI server connected.";
240
241 for (auto &oneDriverInfo : m_ManagedDrivers)
242 {
243 oneDriverInfo->setClientState(true);
244 if (sManager)
245 oneDriverInfo->setHostParameters(sManager->getHost(), sManager->getPort());
246 }
247
248 m_PendingConnection = false;
249 m_ConnectionRetries = MAX_RETRIES;
250
251 emit started();
252}
253
254void ClientManager::serverDisconnected(int exitCode)
255{
256 if (m_PendingConnection)
257 qCDebug(KSTARS_INDI) << "INDI server connection refused.";
258 else
259 qCDebug(KSTARS_INDI) << "INDI server disconnected. Exit code:" << exitCode;
260
261 for (auto &oneDriverInfo : m_ManagedDrivers)
262 {
263 oneDriverInfo->setClientState(false);
264 oneDriverInfo->reset();
265 }
266
267 if (m_PendingConnection)
268 {
269 // Should we retry again?
270 if (m_ConnectionRetries-- > 0)
271 {
272 // Connect again in 1 second.
273 QTimer::singleShot(1000, this, [this]()
274 {
275 qCDebug(KSTARS_INDI) << "Retrying connection again...";
276 if (connectServer() == false)
277 serverDisconnected(0);
278 else
279 m_PendingConnection = false;
280 });
281 }
282 // Nope cannot connect to server.
283 else
284 {
285 m_PendingConnection = false;
286 m_ConnectionRetries = MAX_RETRIES;
287 emit failed(i18n("Failed to connect to INDI server %1:%2", getHost(), getPort()));
288 }
289 }
290 // Did server disconnect abnormally?
291 else if (exitCode < 0)
292 emit terminated(i18n("Connection to INDI host at %1 on port %2 lost. Server disconnected: %3", getHost(), getPort(),
293 exitCode));
294}
295
296const QList<QSharedPointer<DriverInfo>> &ClientManager::getManagedDrivers() const
297{
298 return m_ManagedDrivers;
299}
300
301void ClientManager::establishConnection()
302{
303 qCDebug(KSTARS_INDI)
304 << "INDI: Connecting to local INDI server on port " << getPort() << " ...";
305
306 m_PendingConnection = true;
307 m_ConnectionRetries = 2;
308
309 if (connectServer() == false)
310 serverDisconnected(0);
311 else
312 m_PendingConnection = false;
313}
314
315const QSharedPointer<DriverInfo> &ClientManager::findDriverInfoByName(const QString &name)
316{
317 auto pos = std::find_if(m_ManagedDrivers.begin(), m_ManagedDrivers.end(), [name](QSharedPointer<DriverInfo> oneDriverInfo)
318 {
319 return oneDriverInfo->getName() == name;
320 });
321
322 return *pos;
323}
324
325const QSharedPointer<DriverInfo> &ClientManager::findDriverInfoByLabel(const QString &label)
326{
327 auto pos = std::find_if(m_ManagedDrivers.begin(), m_ManagedDrivers.end(), [label](QSharedPointer<DriverInfo> oneDriverInfo)
328 {
329 return oneDriverInfo->getLabel() == label;
330 });
331
332 return *pos;
333}
334
335void ClientManager::setBLOBEnabled(bool enabled, const QString &device, const QString &property)
336{
337 for(auto &bm : blobManagers)
338 {
339 if (bm->property("device") == device && (property.isEmpty() || bm->property("property") == property))
340 {
341 bm->setEnabled(enabled);
342 return;
343 }
344 }
345}
346
347bool ClientManager::isBLOBEnabled(const QString &device, const QString &property)
348{
349 for(auto &bm : blobManagers)
350 {
351 if (bm->property("device") == device && bm->property("property") == property)
352 return bm->property("enabled").toBool();
353 }
354
355 return false;
356}
BlobManager manages connection to INDI server to handle a specific BLOB.
Definition blobmanager.h:34
void disconnectAll()
disconnectAll Disconnect from server and disconnect all BLOB Managers.
void removeManagedDriver(const QSharedPointer< DriverInfo > &driver)
removeManagedDriver Remove managed driver from pool of drivers managed by this client manager.
void appendManagedDriver(const QSharedPointer< DriverInfo > &driver)
appendManagedDriver Add driver to pool of managed drivers by this client manager.
DeviceInfo is simple class to hold DriverInfo and INDI::BaseDevice associated with a particular devic...
Definition deviceinfo.h:21
QString i18n(const char *text, const TYPE &arg...)
QString name(StandardShortcut id)
void append(QList< T > &&value)
iterator begin()
bool empty() const const
iterator end()
bool removeOne(const AT &t)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QVariant property(const char *name) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
CaseInsensitive
UniqueConnection
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.