1 /* 2 SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #pragma once 8 9 #include "../guideinterface.h" 10 #include "fitsviewer/fitsview.h" 11 12 #include <QAbstractSocket> 13 #include <QJsonArray> 14 #include <QJsonObject> 15 #include <QPointer> 16 #include <QTimer> 17 18 class QTcpSocket; 19 20 namespace Ekos 21 { 22 /** 23 * @class PHD2 24 * Uses external PHD2 for guiding. 25 * 26 * @author Jasem Mutlaq 27 * @version 1.1 28 */ 29 class PHD2 : public GuideInterface 30 { 31 Q_OBJECT 32 33 public: 34 enum PHD2Event 35 { 36 Version, 37 LockPositionSet, 38 Calibrating, 39 CalibrationComplete, 40 StarSelected, 41 StartGuiding, 42 Paused, 43 StartCalibration, 44 AppState, 45 CalibrationFailed, 46 CalibrationDataFlipped, 47 LoopingExposures, 48 LoopingExposuresStopped, 49 SettleBegin, 50 Settling, 51 SettleDone, 52 StarLost, 53 GuidingStopped, 54 Resumed, 55 GuideStep, 56 GuidingDithered, 57 LockPositionLost, 58 Alert, 59 GuideParamChange, 60 ConfigurationChange 61 62 }; 63 enum PHD2State 64 { 65 // these are the states exposed by phd2 66 STOPPED, 67 SELECTED, 68 CALIBRATING, 69 GUIDING, 70 LOSTLOCK, 71 PAUSED, 72 LOOPING, 73 }; 74 enum PHD2Connection 75 { 76 DISCONNECTED, 77 CONNECTED, 78 EQUIPMENT_DISCONNECTED, 79 EQUIPMENT_CONNECTED, 80 CONNECTING, 81 DISCONNECTING, 82 }; 83 enum PHD2MessageType 84 { 85 PHD2_UNKNOWN, 86 PHD2_RESULT, 87 PHD2_EVENT, 88 PHD2_ERROR, 89 }; 90 91 // These are the PHD2 Results and the commands they are associated with 92 enum PHD2ResultType 93 { 94 NO_RESULT, 95 CAPTURE_SINGLE_FRAME, //capture_single_frame 96 CLEAR_CALIBRATION_COMMAND_RECEIVED, //clear_calibration 97 DITHER_COMMAND_RECEIVED, //dither 98 //find_star 99 //flip_calibration 100 //get_algo_param_names 101 //get_algo_param 102 APP_STATE_RECEIVED, //get_app_state 103 //get_calibrated 104 //get_calibration_data 105 IS_EQUIPMENT_CONNECTED, //get_connected 106 //get_cooler_status 107 GET_CURRENT_EQUIPMENT, //get_current_equipment 108 DEC_GUIDE_MODE, //get_dec_guide_mode 109 EXPOSURE_TIME, //get_exposure 110 EXPOSURE_DURATIONS, //get_exposure_durations 111 LOCK_POSITION, //get_lock_position 112 //get_lock_shift_enabled 113 //get_lock_shift_params 114 //get_paused 115 PIXEL_SCALE, //get_pixel_scale 116 //get_profile 117 //get_profiles 118 //get_search_region 119 //get_sensor_temperature 120 STAR_IMAGE, //get_star_image 121 //get_use_subframes 122 GUIDE_COMMAND_RECEIVED, //guide 123 //guide_pulse 124 LOOP, //loop 125 //save_image 126 //set_algo_param 127 CONNECTION_RESULT, //set_connected 128 SET_DEC_GUIDE_MODE_COMMAND_RECEIVED, //set_dec_guide_mode 129 SET_EXPOSURE_COMMAND_RECEIVED, //set_exposure 130 SET_LOCK_POSITION, //set_lock_position 131 //set_lock_shift_enabled 132 //set_lock_shift_params 133 SET_PAUSED_COMMAND_RECEIVED, //set_paused 134 //set_profile 135 //shutdown 136 STOP_CAPTURE_COMMAND_RECEIVED //stop_capture 137 }; 138 139 PHD2(); 140 ~PHD2(); 141 142 //These are the connection methods to connect the external guide program PHD2 143 bool Connect() override; 144 bool Disconnect() override; isConnected()145 bool isConnected() override 146 { 147 return (connection == CONNECTED || connection == EQUIPMENT_CONNECTED); 148 } 149 150 //These are the PHD2 Methods. Only some are implemented in Ekos. 151 152 void captureSingleFrame(); //capture_single_frame 153 bool clearCalibration() override; //clear_calibration 154 bool dither(double pixels) override; //dither 155 //find_star 156 //flip_calibration 157 //get_algo_param_names 158 //get_algo_param 159 void requestAppState(); //get_app_state 160 //get_calibrated 161 //get_calibration_data 162 void checkIfEquipmentConnected(); //get_connected 163 //get_cooler_status 164 void requestCurrentEquipmentUpdate(); //get_current_equipment 165 void checkDEGuideMode(); //get_dec_guide_mode 166 void requestExposureTime(); //get_exposure 167 void requestExposureDurations(); //get_exposure_durations 168 void requestLockPosition(); //get_lock_position 169 //get_lock_shift_enabled 170 //get_lock_shift_params 171 //get_paused 172 void requestPixelScale(); //get_pixel_scale 173 //get_profile 174 //get_profiles 175 //get_search_region 176 //get_sensor_temperature 177 void requestStarImage(int size); //get_star_image 178 //get_use_subframes 179 bool guide() override; //guide 180 //guide_pulse 181 void loop(); //loop 182 //save_image 183 //set_algo_param 184 void connectEquipment(bool enable);//set_connected 185 void requestSetDEGuideMode(bool deEnabled, bool nEnabled, bool sEnabled); //set_dec_guide_mode 186 void requestSetExposureTime(int time); //set_exposure 187 void setLockPosition(double x, double y); //set_lock_position 188 //set_lock_shift_enabled 189 //set_lock_shift_params 190 bool suspend() override; //set_paused 191 bool resume() override; //set_paused 192 //set_profile 193 //shutdown 194 bool abort() override; //stop_capture 195 196 bool calibrate() override; //Note PHD2 does not have a separate calibrate command. This is unused. 197 void setGuideView(FITSView *guideView); 198 getCurrentCamera()199 QString getCurrentCamera() 200 { 201 return currentCamera; 202 } getCurrentMount()203 QString getCurrentMount() 204 { 205 return currentMount; 206 } getCurrentAuxMount()207 QString getCurrentAuxMount() 208 { 209 return currentAuxMount; 210 } 211 isCurrentCameraNotInEkos()212 bool isCurrentCameraNotInEkos() 213 { 214 return currentCameraIsNotInEkos; 215 } setCurrentCameraIsNotInEkos(bool enable)216 void setCurrentCameraIsNotInEkos(bool enable) 217 { 218 currentCameraIsNotInEkos = enable; 219 } 220 221 private slots: 222 223 void readPHD2(); 224 void displayError(QAbstractSocket::SocketError socketError); 225 226 private: 227 QPointer<FITSView> guideFrame; 228 229 QVector<QPointF> errorLog; 230 231 void sendPHD2Request(const QString &method, const QJsonArray &args = QJsonArray()); 232 void sendRpcCall(QJsonObject &call, PHD2ResultType resultType); 233 void sendNextRpcCall(); 234 235 void processPHD2Event(const QJsonObject &jsonEvent, const QByteArray &rawResult); 236 void processPHD2Result(const QJsonObject &jsonObj, const QByteArray &rawResult); 237 void processStarImage(const QJsonObject &jsonStarFrame); 238 void processPHD2State(const QString &phd2State); 239 void handlePHD2AppState(PHD2State state); 240 void processPHD2Error(const QJsonObject &jsonError, const QByteArray &rawResult); 241 242 PHD2ResultType takeRequestFromList(const QJsonObject &response); 243 244 QPointer<QTcpSocket> tcpSocket; 245 int nextRpcId { 1 }; 246 247 QHash<QString, PHD2Event> events; // maps event name to event type 248 QHash<QString, PHD2ResultType> methodResults; // maps method name to result type 249 250 int pendingRpcId; // ID of outstanding RPC call 251 PHD2ResultType pendingRpcResultType { NO_RESULT }; // result type of outstanding RPC call 252 bool starImageRequested { false }; // true when there is an outstanding star image request 253 254 struct RpcCall 255 { 256 QJsonObject call; 257 PHD2ResultType resultType; 258 RpcCall() = default; RpcCallRpcCall259 RpcCall(const QJsonObject &call_, PHD2ResultType resultType_) : call(call_), resultType(resultType_) { } 260 }; 261 QVector<RpcCall> rpcRequestQueue; 262 263 PHD2State state { STOPPED }; 264 bool isDitherActive { false }; 265 bool isSettling { false }; 266 PHD2Connection connection { DISCONNECTED }; 267 PHD2Event event { Alert }; 268 uint8_t setConnectedRetries { 0 }; 269 270 void setEquipmentConnected(); 271 void updateGuideParameters(); 272 void ResetConnectionState(); 273 274 QTimer *abortTimer; 275 QTimer *ditherTimer; 276 QTimer *stateTimer; 277 278 double pixelScale = 0; 279 280 QString logValidExposureTimes; 281 282 QString currentCamera; 283 QString currentMount; 284 QString currentAuxMount; 285 bool currentCameraIsNotInEkos; 286 287 uint8_t m_PHD2ReconnectCounter {0}; 288 289 // Wait this many milliseconds before trying to reconnect again to PHD2 290 static const uint32_t PHD2_RECONNECT_TIMEOUT {3000}; 291 // Try to connect this many times before giving up. 292 static const uint8_t PHD2_RECONNECT_THRESHOLD {10}; 293 294 }; 295 296 } 297