File indexing completed on 2024-07-21 06:28:24

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 #pragma once
0010 
0011 #include "indicommon.h"
0012 
0013 #include <indiproperty.h>
0014 #include <basedevice.h>
0015 
0016 #include <QObject>
0017 #include <QVariant>
0018 #include <QJsonArray>
0019 
0020 #ifndef KSTARS_LITE
0021 #include <QDBusArgument>
0022 #endif
0023 
0024 #define MAXINDIFILENAME 512
0025 
0026 class ClientManager;
0027 class DriverInfo;
0028 class DeviceInfo;
0029 class QTimer;
0030 class QFile;
0031 
0032 using Properties = INDI::BaseDevice::Properties;
0033 
0034 // INDI Standard Device Namespace
0035 namespace ISD
0036 {
0037 
0038 typedef enum { PARK_UNKNOWN, PARK_PARKED, PARK_PARKING, PARK_UNPARKING, PARK_UNPARKED, PARK_ERROR } ParkStatus;
0039 
0040 // Create instances as per driver interface.
0041 class ConcreteDevice;
0042 class Mount;
0043 class Camera;
0044 class Guider;
0045 class Focuser;
0046 class FilterWheel;
0047 class Dome;
0048 class GPS;
0049 class Weather;
0050 class AdaptiveOptics;
0051 class DustCap;
0052 class LightBox;
0053 class Detector;
0054 class Rotator;
0055 class Spectrograph;
0056 class Correlator;
0057 class Auxiliary;
0058 
0059 class GDSetCommand : public QObject
0060 {
0061         Q_OBJECT
0062 
0063     public:
0064         GDSetCommand(INDI_PROPERTY_TYPE inPropertyType, const QString &inProperty, const QString &inElement,
0065                      QVariant qValue, QObject *parent);
0066         INDI_PROPERTY_TYPE propType;
0067 
0068         QString indiProperty;
0069         QString indiElement;
0070         QVariant elementValue;
0071 };
0072 
0073 /**
0074  * @class GDInterface
0075  * GDInterface is the Generic Device <i>Interface</i> for INDI devices. It is used as part of the Decorator Pattern when initially a new INDI device is created as a
0076  * Generic Device in INDIListener. If the device registers an INDI Standard Property belonging to one specific device type (e.g. Telescope), then the device functionality
0077  * is extended to the particular device type.
0078  *
0079  * DeviceDecorator subclasses GDInterface and calls concrete decorators methods.
0080  *
0081  * @author Jasem Mutlaq
0082  */
0083 class GDInterface : public QObject
0084 {
0085         Q_OBJECT
0086 
0087     public:
0088         explicit GDInterface(QObject *parent) : QObject(parent) {}
0089 
0090         // Property registration
0091         virtual void registerProperty(INDI::Property prop) = 0;
0092         virtual void removeProperty(INDI::Property prop) = 0;
0093         virtual void updateProperty(INDI::Property prop) = 0;
0094 
0095         // Property updates
0096         virtual void processSwitch(INDI::Property prop) = 0;
0097         virtual void processText(INDI::Property prop) = 0;
0098         virtual void processNumber(INDI::Property prop) = 0;
0099         virtual void processLight(INDI::Property prop) = 0;
0100         virtual bool processBLOB(INDI::Property prop) = 0;
0101 
0102         // Messages
0103         virtual void processMessage(int messageID) = 0;
0104 };
0105 
0106 /**
0107  * @class GenericDevice
0108  * GenericDevice is the Generic Device for INDI devices. When a new INDI device is created in INDIListener, it gets created as a GenericDevice initially. If the device
0109  * registers a standard property that is a key property to a device type family (e.g. Number property EQUATORIAL_EOD_COORD signifies a Telescope device), then the specialized version of
0110  * the device is extended via the Decorator Pattern.
0111  *
0112  * GenericDevice handles common functions shared across many devices such as time and location handling, configuration processing, retrieving information about properties, driver info..etc.
0113  *
0114  * @author Jasem Mutlaq
0115  */
0116 class GenericDevice : public GDInterface
0117 {
0118         Q_OBJECT
0119         Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.INDI.GenericDevice")
0120         Q_PROPERTY(QString name READ getDeviceName)
0121         Q_PROPERTY(uint32_t driverInterface READ getDriverInterface)
0122         Q_PROPERTY(QString driverVersion READ getDriverVersion)
0123         Q_PROPERTY(bool connected READ isConnected)
0124 
0125     public:
0126         explicit GenericDevice(DeviceInfo &idv, ClientManager *cm, QObject *parent = nullptr);
0127         virtual ~GenericDevice() override;
0128 
0129         virtual void registerProperty(INDI::Property prop) override;
0130         virtual void removeProperty(INDI::Property prop) override;
0131         virtual void updateProperty(INDI::Property prop) override;
0132 
0133         virtual void processSwitch(INDI::Property prop) override;
0134         virtual void processText(INDI::Property prop) override;
0135         virtual void processNumber(INDI::Property prop) override;
0136         virtual void processLight(INDI::Property prop) override;
0137 
0138         /**
0139              * @brief processBLOB Process Binary BLOB
0140              * @param bp pointer to binary blob.
0141              * @return Return true of BLOB was successfully processed. If a concrete device does not process the blob, it should
0142              * return false to allow sibling or parent devices to process the blob.
0143              */
0144         virtual bool processBLOB(INDI::Property prop) override;
0145         virtual void processMessage(int messageID) override;
0146 
0147         virtual const QString &getDeviceName() const;
0148         virtual const QSharedPointer<DriverInfo> &getDriverInfo() const
0149         {
0150             return m_DriverInfo;
0151         }
0152         virtual DeviceInfo *getDeviceInfo() const
0153         {
0154             return m_DeviceInfo;
0155         }
0156         virtual Properties getProperties()
0157         {
0158             return m_BaseDevice.getProperties();
0159         }
0160         virtual uint32_t getDriverInterface()
0161         {
0162             return m_DriverInterface;
0163         }
0164         virtual QString getDriverVersion()
0165         {
0166             return m_DriverVersion;
0167         }
0168 
0169         virtual bool setConfig(INDIConfig tConfig);
0170         virtual bool isConnected() const
0171         {
0172             return m_Connected;
0173         }
0174         virtual bool isReady() const
0175         {
0176             return m_Ready;
0177         }
0178         virtual INDI::BaseDevice getBaseDevice() const
0179         {
0180             return m_BaseDevice;
0181         }
0182         ClientManager *getClientManager() const
0183         {
0184             return m_ClientManager;
0185         }
0186         virtual bool getMinMaxStep(const QString &propName, const QString &elementName, double *min, double *max,
0187                                    double *step);
0188         virtual IPState getState(const QString &propName);
0189         virtual IPerm getPermission(const QString &propName);
0190         virtual INDI::Property getProperty(const QString &propName);
0191         virtual bool getJSONProperty(const QString &propName, QJsonObject &propObject, bool compact);
0192         virtual bool getJSONBLOB(const QString &propName, const QString &elementName, QJsonObject &blobObject);
0193         virtual bool setJSONProperty(const QString &propName, const QJsonArray &propElements);
0194 
0195         bool findConcreteDevice(uint32_t interface, QSharedPointer<ConcreteDevice> &device);
0196 
0197         void sendNewProperty(INDI::Property prop);
0198         /** @brief Send new Text command to server */
0199         void sendNewText(INDI::Property prop);
0200         /** @brief Send new Number command to server */
0201         void sendNewNumber(INDI::Property prop);
0202         /** @brief Send new Switch command to server */
0203         void sendNewSwitch(INDI::Property prop);
0204 
0205         // Convinence functions
0206         ISD::Mount *getMount();
0207         ISD::Camera *getCamera();
0208         ISD::Guider *getGuider();
0209         ISD::Focuser *getFocuser();
0210         ISD::FilterWheel *getFilterWheel();
0211         ISD::Dome *getDome();
0212         ISD::GPS *getGPS();
0213         ISD::Weather *getWeather();
0214         ISD::AdaptiveOptics *getAdaptiveOptics();
0215         ISD::DustCap *getDustCap();
0216         ISD::LightBox *getLightBox();
0217         ISD::Detector *getDetector();
0218         ISD::Rotator *getRotator();
0219         ISD::Spectrograph *getSpectrograph();
0220         ISD::Correlator *getCorrelator();
0221         ISD::Auxiliary *getAuxiliary();
0222 
0223         Q_SCRIPTABLE Q_NOREPLY void Connect();
0224         Q_SCRIPTABLE Q_NOREPLY void Disconnect();
0225         bool setProperty(QObject *);
0226 
0227     protected slots:
0228         virtual void resetWatchdog();
0229 
0230     protected:
0231         void createDeviceInit();
0232         void updateTime();
0233         void updateLocation();
0234         /**
0235          * @brief generateDevices Generate concrete devices based on DRIVER_INTERFACE
0236          * @return True if at least one device is generated, false otherwise.
0237          */
0238         bool generateDevices();
0239         void handleTimeout();
0240         void checkTimeUpdate();
0241         void checkLocationUpdate();
0242 
0243     protected:
0244         uint32_t m_DriverInterface { 0 };
0245         QString m_DriverVersion;
0246         QMap<uint32_t, QSharedPointer<ConcreteDevice>> m_ConcreteDevices;
0247 
0248     signals:
0249         void Connected();
0250         void Disconnected();
0251 
0252         void propertyUpdated(INDI::Property prop);
0253         void messageUpdated(int messageID);
0254 
0255         void interfaceDefined();
0256         void systemPortDetected();
0257         void propertyDefined(INDI::Property prop);
0258         void propertyDeleted(INDI::Property prop);
0259         void ready();
0260 
0261         // These are emitted as soon as the driver interface defines them
0262         void newMount(Mount *device);
0263         void newCamera(Camera *device);
0264         void newGuider(Guider *device);
0265         void newFocuser(Focuser *device);
0266         void newFilterWheel(FilterWheel *device);
0267         void newDome(Dome *device);
0268         void newGPS(GPS *device);
0269         void newWeather(Weather *device);
0270         void newAdaptiveOptics(AdaptiveOptics *device);
0271         void newDustCap(DustCap *device);
0272         void newLightBox(LightBox *device);
0273         void newDetector(Detector *device);
0274         void newRotator(Rotator *device);
0275         void newSpectrograph(Spectrograph *device);
0276         void newCorrelator(Correlator *device);
0277         void newAuxiliary(Auxiliary *device);
0278 
0279     private:
0280 
0281         class StreamFileMetadata
0282         {
0283             public:
0284                 QString device;
0285                 QString property;
0286                 QString element;
0287                 QFile *file { nullptr};
0288         };
0289 
0290         static void registerDBusType();
0291         bool m_Connected { false };
0292         bool m_Ready {false};
0293         QString m_Name;
0294         QSharedPointer<DriverInfo> m_DriverInfo;
0295         DeviceInfo *m_DeviceInfo { nullptr };
0296         INDI::BaseDevice m_BaseDevice;
0297         ClientManager *m_ClientManager { nullptr };
0298         QTimer *watchDogTimer { nullptr };
0299         QTimer *m_ReadyTimer {nullptr};
0300         QTimer *m_TimeUpdateTimer {nullptr};
0301         QTimer *m_LocationUpdateTimer {nullptr};
0302         QList<StreamFileMetadata> streamFileMetadata;
0303 
0304         static uint8_t getID()
0305         {
0306             return m_ID++;
0307         }
0308         static uint8_t m_ID;
0309 };
0310 
0311 void switchToJson(INDI::Property prop, QJsonObject &propObject, bool compact = true);
0312 void textToJson(INDI::Property prop, QJsonObject &propObject, bool compact = true);
0313 void numberToJson(INDI::Property prop, QJsonObject &propObject, bool compact = true);
0314 void lightToJson(INDI::Property prop, QJsonObject &propObject, bool compact = true);
0315 void propertyToJson(INDI::Property prop, QJsonObject &propObject, bool compact = true);
0316 
0317 }
0318 
0319 
0320 #ifndef KSTARS_LITE
0321 Q_DECLARE_METATYPE(ISD::ParkStatus)
0322 QDBusArgument &operator<<(QDBusArgument &argument, const ISD::ParkStatus &source);
0323 const QDBusArgument &operator>>(const QDBusArgument &argument, ISD::ParkStatus &dest);
0324 #endif