File indexing completed on 2024-04-21 03:44:08
0001 /* 0002 SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 Handle INDI Standard properties. 0007 */ 0008 0009 #include "indilistener.h" 0010 0011 #include "clientmanager.h" 0012 #include "deviceinfo.h" 0013 #include "kstars.h" 0014 #include "Options.h" 0015 0016 #include "auxiliary/ksnotification.h" 0017 0018 #include <knotification.h> 0019 0020 #include <basedevice.h> 0021 #include <indi_debug.h> 0022 0023 INDIListener *INDIListener::_INDIListener = nullptr; 0024 0025 INDIListener *INDIListener::Instance() 0026 { 0027 if (_INDIListener == nullptr) 0028 { 0029 _INDIListener = new INDIListener(KStars::Instance()); 0030 qRegisterMetaType<INDI::BaseDevice>("INDI::BaseDevice"); 0031 } 0032 0033 return _INDIListener; 0034 } 0035 0036 bool INDIListener::findDevice(const QString &name, QSharedPointer<ISD::GenericDevice> &device) 0037 { 0038 auto all = devices(); 0039 auto it = std::find_if(all.begin(), all.end(), [name](auto & oneDevice) 0040 { 0041 return oneDevice->getDeviceName() == name; 0042 }); 0043 if (it == all.end()) 0044 return false; 0045 0046 device = *it; 0047 return true; 0048 } 0049 0050 INDIListener::INDIListener(QObject *parent) : QObject(parent) {} 0051 0052 bool INDIListener::getDevice(const QString &name, QSharedPointer<ISD::GenericDevice> &device) const 0053 { 0054 for (auto &oneDevice : m_Devices) 0055 { 0056 if (oneDevice->getDeviceName() == name) 0057 { 0058 device = oneDevice; 0059 return true; 0060 } 0061 } 0062 return false; 0063 } 0064 0065 void INDIListener::addClient(ClientManager *cm) 0066 { 0067 qCDebug(KSTARS_INDI) 0068 << "INDIListener: Adding a new client manager to INDI listener.."; 0069 0070 clients.append(cm); 0071 0072 connect(cm, &ClientManager::newINDIDevice, this, &INDIListener::processDevice); 0073 connect(cm, &ClientManager::removeINDIDevice, this, &INDIListener::removeDevice); 0074 0075 connect(cm, &ClientManager::newINDIProperty, this, &INDIListener::registerProperty); 0076 connect(cm, &ClientManager::updateINDIProperty, this, &INDIListener::updateProperty); 0077 connect(cm, &ClientManager::removeINDIProperty, this, &INDIListener::removeProperty); 0078 0079 connect(cm, &ClientManager::newINDIMessage, this, 0080 &INDIListener::processMessage); 0081 connect(cm, &ClientManager::newINDIUniversalMessage, this, 0082 &INDIListener::processUniversalMessage); 0083 } 0084 0085 void INDIListener::removeClient(ClientManager *cm) 0086 { 0087 qCDebug(KSTARS_INDI) << "INDIListener: Removing client manager for server" 0088 << cm->getHost() << "@" << cm->getPort(); 0089 0090 cm->disconnect(this); 0091 clients.removeOne(cm); 0092 0093 auto managedDrivers = cm->getManagedDrivers(); 0094 for (auto &oneDriverInfo : managedDrivers) 0095 cm->removeManagedDriver(oneDriverInfo); 0096 } 0097 0098 void INDIListener::processDevice(DeviceInfo *dv) 0099 { 0100 ClientManager *cm = qobject_cast<ClientManager *>(sender()); 0101 Q_ASSERT_X(cm, __FUNCTION__, "Client manager is not valid."); 0102 0103 qCDebug(KSTARS_INDI) << "INDIListener: New device" << dv->getDeviceName(); 0104 0105 QSharedPointer<ISD::GenericDevice> gd; 0106 gd.reset(new ISD::GenericDevice(*dv, cm, this)); 0107 0108 auto isConnected = gd->isConnected(); 0109 // If already connected, we need to process all the properties as well 0110 // Register all existing properties 0111 for (auto &oneProperty : dv->getBaseDevice().getProperties()) 0112 { 0113 gd->registerProperty(oneProperty); 0114 if (isConnected) 0115 { 0116 switch (oneProperty.getType()) 0117 { 0118 case INDI_SWITCH: 0119 gd->processSwitch(oneProperty.getSwitch()); 0120 break; 0121 case INDI_NUMBER: 0122 gd->processNumber(oneProperty.getNumber()); 0123 break; 0124 case INDI_TEXT: 0125 gd->processText(oneProperty.getText()); 0126 break; 0127 case INDI_LIGHT: 0128 gd->processLight(oneProperty.getLight()); 0129 break; 0130 default: 0131 break; 0132 } 0133 } 0134 } 0135 0136 m_Devices.append(std::move(gd)); 0137 emit newDevice(gd); 0138 0139 } 0140 0141 void INDIListener::removeDevice(const QString &deviceName) 0142 { 0143 qCDebug(KSTARS_INDI) << "INDIListener: Removing device" << deviceName; 0144 0145 for (auto oneDevice : qAsConst(m_Devices)) 0146 { 0147 if (oneDevice->getDeviceName() == deviceName) 0148 { 0149 // Remove from list first 0150 m_Devices.removeOne(oneDevice); 0151 // Then emit a signal to inform subscribers that this device is removed. 0152 emit deviceRemoved(oneDevice); 0153 // Delete this device later. 0154 oneDevice->deleteLater(); 0155 return; 0156 } 0157 } 0158 } 0159 0160 void INDIListener::registerProperty(INDI::Property prop) 0161 { 0162 if (!prop.getRegistered()) 0163 return; 0164 0165 qCDebug(KSTARS_INDI) << "<" << prop.getDeviceName() << ">: <" << prop.getName() 0166 << ">"; 0167 0168 for (auto &oneDevice : m_Devices) 0169 { 0170 if (oneDevice->getDeviceName() == prop.getDeviceName()) 0171 { 0172 oneDevice->registerProperty(prop); 0173 return; 0174 } 0175 } 0176 } 0177 0178 void INDIListener::removeProperty(INDI::Property prop) 0179 { 0180 for (auto &oneDevice : m_Devices) 0181 { 0182 if (oneDevice->getDeviceName() == prop.getDeviceName()) 0183 { 0184 oneDevice->removeProperty(prop); 0185 return; 0186 } 0187 } 0188 } 0189 0190 void INDIListener::updateProperty(INDI::Property prop) 0191 { 0192 for (auto &oneDevice : m_Devices) 0193 { 0194 if (oneDevice->getDeviceName() == prop.getDeviceName()) 0195 { 0196 oneDevice->updateProperty(prop); 0197 break; 0198 } 0199 } 0200 } 0201 0202 void INDIListener::processMessage(INDI::BaseDevice dp, int messageID) 0203 { 0204 for (auto &oneDevice : m_Devices) 0205 { 0206 if (oneDevice->getDeviceName() == dp.getDeviceName()) 0207 { 0208 oneDevice->processMessage(messageID); 0209 break; 0210 } 0211 } 0212 } 0213 0214 void INDIListener::processUniversalMessage(const QString &message) 0215 { 0216 QString displayMessage = message; 0217 // Remove timestamp info as it is not suitable for message box 0218 int colonIndex = displayMessage.indexOf(": "); 0219 if (colonIndex > 0) 0220 displayMessage = displayMessage.mid(colonIndex + 2); 0221 0222 // Special case for Alignment since it is not tied to a device 0223 if (displayMessage.startsWith("[ALIGNMENT]")) 0224 { 0225 qCDebug(KSTARS_INDI) << "AlignmentSubSystem:" << displayMessage; 0226 return; 0227 } 0228 0229 if (Options::messageNotificationINDI()) 0230 { 0231 KSNotification::event(QLatin1String("IndiServerMessage"), displayMessage, 0232 KSNotification::INDI, KSNotification::Warn); 0233 } 0234 else 0235 { 0236 KSNotification::transient(displayMessage, i18n("INDI Server Message")); 0237 } 0238 }