File indexing completed on 2024-05-12 15:23:37

0001 /*
0002     SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "../guideinterface.h"
0010 
0011 #include <QAbstractSocket>
0012 #include <QJsonArray>
0013 #include <QJsonObject>
0014 #include <QPointer>
0015 #include <QTimer>
0016 
0017 class FITSView;
0018 class QTcpSocket;
0019 
0020 namespace Ekos
0021 {
0022 /**
0023  * @class  PHD2
0024  * Uses external PHD2 for guiding.
0025  *
0026  * @author Jasem Mutlaq
0027  * @version 1.1
0028  */
0029 class PHD2 : public GuideInterface
0030 {
0031         Q_OBJECT
0032 
0033     public:
0034         enum PHD2Event
0035         {
0036             Version,
0037             LockPositionSet,
0038             Calibrating,
0039             CalibrationComplete,
0040             StarSelected,
0041             StartGuiding,
0042             Paused,
0043             StartCalibration,
0044             AppState,
0045             CalibrationFailed,
0046             CalibrationDataFlipped,
0047             LoopingExposures,
0048             LoopingExposuresStopped,
0049             SettleBegin,
0050             Settling,
0051             SettleDone,
0052             StarLost,
0053             GuidingStopped,
0054             Resumed,
0055             GuideStep,
0056             GuidingDithered,
0057             LockPositionLost,
0058             Alert,
0059             GuideParamChange,
0060             ConfigurationChange
0061 
0062         };
0063         enum PHD2State
0064         {
0065             // these are the states exposed by phd2
0066             STOPPED,
0067             SELECTED,
0068             CALIBRATING,
0069             GUIDING,
0070             LOSTLOCK,
0071             PAUSED,
0072             LOOPING,
0073             DITHERING,
0074         };
0075         enum PHD2Connection
0076         {
0077             DISCONNECTED,
0078             CONNECTED,
0079             EQUIPMENT_DISCONNECTED,
0080             EQUIPMENT_CONNECTED,
0081             CONNECTING,
0082             DISCONNECTING,
0083         };
0084         enum PHD2MessageType
0085         {
0086             PHD2_UNKNOWN,
0087             PHD2_RESULT,
0088             PHD2_EVENT,
0089             PHD2_ERROR,
0090         };
0091 
0092         // These are the PHD2 Results and the commands they are associated with
0093         enum PHD2ResultType
0094         {
0095             NO_RESULT,
0096             CAPTURE_SINGLE_FRAME,                   //capture_single_frame
0097             CLEAR_CALIBRATION_COMMAND_RECEIVED,     //clear_calibration
0098             DITHER_COMMAND_RECEIVED,                //dither
0099             //find_star
0100             //flip_calibration
0101             //get_algo_param_names
0102             //get_algo_param
0103             APP_STATE_RECEIVED,                     //get_app_state
0104             //get_calibrated
0105             //get_calibration_data
0106             IS_EQUIPMENT_CONNECTED,                 //get_connected
0107             //get_cooler_status
0108             GET_CURRENT_EQUIPMENT,                  //get_current_equipment
0109             DEC_GUIDE_MODE,                         //get_dec_guide_mode
0110             EXPOSURE_TIME,                          //get_exposure
0111             EXPOSURE_DURATIONS,                     //get_exposure_durations
0112             LOCK_POSITION,                          //get_lock_position
0113             //get_lock_shift_enabled
0114             //get_lock_shift_params
0115             //get_paused
0116             PIXEL_SCALE,                            //get_pixel_scale
0117             //get_profile
0118             //get_profiles
0119             //get_search_region
0120             //get_sensor_temperature
0121             STAR_IMAGE,                             //get_star_image
0122             //get_use_subframes
0123             GUIDE_COMMAND_RECEIVED,                 //guide
0124             //guide_pulse
0125             LOOP,                                   //loop
0126             //save_image
0127             //set_algo_param
0128             CONNECTION_RESULT,                      //set_connected
0129             SET_DEC_GUIDE_MODE_COMMAND_RECEIVED,    //set_dec_guide_mode
0130             SET_EXPOSURE_COMMAND_RECEIVED,          //set_exposure
0131             SET_LOCK_POSITION,                      //set_lock_position
0132             //set_lock_shift_enabled
0133             //set_lock_shift_params
0134             SET_PAUSED_COMMAND_RECEIVED,            //set_paused
0135             //set_profile
0136             //shutdown
0137             STOP_CAPTURE_COMMAND_RECEIVED           //stop_capture
0138         };
0139 
0140         PHD2();
0141         ~PHD2();
0142 
0143         //These are the connection methods to connect the external guide program PHD2
0144         bool Connect() override;
0145         bool Disconnect() override;
0146         bool isConnected() override
0147         {
0148             return (connection == CONNECTED || connection == EQUIPMENT_CONNECTED);
0149         }
0150 
0151         //These are the PHD2 Methods.  Only some are implemented in Ekos.
0152 
0153         void captureSingleFrame();              //capture_single_frame
0154         bool clearCalibration() override;       //clear_calibration
0155         bool dither(double pixels) override;    //dither
0156         //find_star
0157         //flip_calibration
0158         //get_algo_param_names
0159         //get_algo_param
0160         void requestAppState();                //get_app_state
0161         //get_calibrated
0162         //get_calibration_data
0163         void checkIfEquipmentConnected();       //get_connected
0164         //get_cooler_status
0165         void requestCurrentEquipmentUpdate();     //get_current_equipment
0166         void checkDEGuideMode();                //get_dec_guide_mode
0167         void requestExposureTime();             //get_exposure
0168         void requestExposureDurations();        //get_exposure_durations
0169         void requestLockPosition();             //get_lock_position
0170         //get_lock_shift_enabled
0171         //get_lock_shift_params
0172         //get_paused
0173         void requestPixelScale();               //get_pixel_scale
0174         //get_profile
0175         //get_profiles
0176         //get_search_region
0177         //get_sensor_temperature
0178         void requestStarImage(int size);        //get_star_image
0179         //get_use_subframes
0180         bool guide() override;                  //guide
0181         //guide_pulse
0182         void loop();                            //loop
0183         //save_image
0184         //set_algo_param
0185         void connectEquipment(bool enable);//set_connected
0186         void requestSetDEGuideMode(bool deEnabled, bool nEnabled, bool sEnabled);           //set_dec_guide_mode
0187         void requestSetExposureTime(int time);  //set_exposure
0188         void setLockPosition(double x, double y); //set_lock_position
0189         //set_lock_shift_enabled
0190         //set_lock_shift_params
0191         bool suspend() override;                //set_paused
0192         bool resume() override;                 //set_paused
0193         //set_profile
0194         //shutdown
0195         bool abort() override;                  //stop_capture
0196 
0197         bool calibrate() override; //Note PHD2 does not have a separate calibrate command.  This is unused.
0198         void setGuideView(const QSharedPointer<FITSView> &guideView);
0199 
0200         QString getCurrentCamera()
0201         {
0202             return currentCamera;
0203         }
0204         QString getCurrentMount()
0205         {
0206             return currentMount;
0207         }
0208         QString getCurrentAuxMount()
0209         {
0210             return currentAuxMount;
0211         }
0212 
0213         bool isCurrentCameraNotInEkos()
0214         {
0215             return currentCameraIsNotInEkos;
0216         }
0217         void setCurrentCameraIsNotInEkos(bool enable)
0218         {
0219             currentCameraIsNotInEkos = enable;
0220         }
0221 
0222     private slots:
0223 
0224         void readPHD2();
0225         void displayError(QAbstractSocket::SocketError socketError);
0226 
0227     private:
0228         QSharedPointer<FITSView> m_GuideFrame;
0229 
0230         QVector<QPointF> errorLog;
0231 
0232         void sendPHD2Request(const QString &method, const QJsonArray &args = QJsonArray());
0233         void sendRpcCall(QJsonObject &call, PHD2ResultType resultType);
0234         void sendNextRpcCall();
0235 
0236         void processPHD2Event(const QJsonObject &jsonEvent, const QByteArray &rawResult);
0237         void processPHD2Result(const QJsonObject &jsonObj, const QByteArray &rawResult);
0238         void processStarImage(const QJsonObject &jsonStarFrame);
0239         void processPHD2State(const QString &phd2State);
0240         void handlePHD2AppState(PHD2State state);
0241         void processPHD2Error(const QJsonObject &jsonError, const QByteArray &rawResult);
0242 
0243         PHD2ResultType takeRequestFromList(const QJsonObject &response);
0244 
0245         QPointer<QTcpSocket> tcpSocket;
0246         int nextRpcId { 1 };
0247 
0248         QHash<QString, PHD2Event> events;                     // maps event name to event type
0249         QHash<QString, PHD2ResultType> methodResults;         // maps method name to result type
0250 
0251         int pendingRpcId;                         // ID of outstanding RPC call
0252         PHD2ResultType pendingRpcResultType { NO_RESULT };      // result type of outstanding RPC call
0253         bool starImageRequested { false };        // true when there is an outstanding star image request
0254 
0255         struct RpcCall
0256         {
0257             QJsonObject call;
0258             PHD2ResultType resultType;
0259             RpcCall() = default;
0260             RpcCall(const QJsonObject &call_, PHD2ResultType resultType_) : call(call_), resultType(resultType_) { }
0261         };
0262         QVector<RpcCall> rpcRequestQueue;
0263 
0264         PHD2State state { STOPPED };
0265         bool isDitherActive { false };
0266         bool isSettling { false };
0267         PHD2Connection connection { DISCONNECTED };
0268         PHD2Event event { Alert };
0269         uint8_t setConnectedRetries { 0 };
0270 
0271         void setEquipmentConnected();
0272         void updateGuideParameters();
0273         void ResetConnectionState();
0274 
0275         QTimer *abortTimer;
0276         QTimer *ditherTimer;
0277         QTimer *stateTimer;
0278 
0279         double pixelScale = 0;
0280 
0281         QString logValidExposureTimes;
0282 
0283         QString currentCamera;
0284         QString currentMount;
0285         QString currentAuxMount;
0286         bool currentCameraIsNotInEkos;
0287 
0288         uint8_t m_PHD2ReconnectCounter {0};
0289 
0290         // Wait this many milliseconds before trying to reconnect again to PHD2
0291         static const uint32_t PHD2_RECONNECT_TIMEOUT {3000};
0292         // Try to connect this many times before giving up.
0293         static const uint8_t PHD2_RECONNECT_THRESHOLD {10};
0294 
0295 };
0296 
0297 }