File indexing completed on 2024-04-28 03:43:18

0001 /*
0002     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "sequencejobstate.h"
0010 #include "indi/indistd.h"
0011 #include "indi/indicamera.h"
0012 ////#include "ekos/auxiliary/filtermanager.h"
0013 
0014 #include <QTableWidgetItem>
0015 
0016 class SkyPoint;
0017 
0018 /**
0019  * @class SequenceJob
0020  * @short Sequence Job is a container for the details required to capture a series of images.
0021  *
0022  * @author Jasem Mutlaq
0023  * @version 1.0
0024  */
0025 namespace Ekos
0026 {
0027 
0028 class CaptureDeviceAdaptor;
0029 
0030 class SequenceJob : public QObject
0031 {
0032         Q_OBJECT
0033 
0034     public:
0035         static QString const &ISOMarker;
0036         static const QStringList StatusStrings();
0037 
0038         // Core Properties
0039         typedef enum
0040         {
0041             // Bool
0042             SJ_EnforceTemperature,
0043             // Bool
0044             // SJ_EnforceStartGuiderDrift, // no specific option
0045             // Bool
0046             SJ_GuiderActive,
0047             // Double
0048             SJ_Exposure,
0049             // QString
0050             SJ_Filter,
0051             // QString
0052             SJ_Format,
0053             // QString
0054             SJ_Encoding,
0055             // QPoint
0056             SJ_Binning,
0057             // QRect
0058             SJ_ROI,
0059             // QString
0060             SJ_FullPrefix,
0061             // Int
0062             SJ_Count,
0063             // Int
0064             SJ_Delay,
0065             // QString
0066             SJ_ISO,
0067             // Int
0068             SJ_ISOIndex,
0069             // Double
0070             SJ_Gain,
0071             // Double
0072             SJ_Offset,
0073             // QString
0074             SJ_TargetName,
0075             //QString
0076             SJ_LocalDirectory,
0077             // QString
0078             SJ_PlaceholderFormat,
0079             // Uint
0080             SJ_PlaceholderSuffix,
0081             // QString
0082             SJ_RemoteDirectory,
0083             // QString
0084             SJ_RemoteFormatDirectory,
0085             // QString
0086             SJ_RemoteFormatFilename,
0087             // QString
0088             SJ_Filename,
0089             // Double
0090             SJ_TargetADU,
0091             // Double
0092             SJ_TargetADUTolerance,
0093             // QString
0094             SJ_Signature,
0095             // Int
0096             SJ_DitherPerJobFrequency
0097         } PropertyID;
0098 
0099         typedef enum
0100         {
0101             JOBTYPE_BATCH,    /* regular batch job            */
0102             JOBTYPE_PREVIEW,  /* previews (single or looping) */
0103             JOBTYPE_DARKFLAT  /* capturing dark flats         */
0104         } SequenceJobType;
0105 
0106         ////////////////////////////////////////////////////////////////////////
0107         /// Constructors
0108         ////////////////////////////////////////////////////////////////////////
0109         SequenceJob(const QSharedPointer<CaptureDeviceAdaptor> cp,
0110                     const QSharedPointer<CaptureModuleState> sharedState,
0111                     SequenceJobType jobType, XMLEle *root = nullptr, QString targetName = "");
0112         SequenceJob(XMLEle *root, QString targetName);
0113         ~SequenceJob() = default;
0114 
0115         ////////////////////////////////////////////////////////////////////////
0116         /// Capture Fuctions
0117         ////////////////////////////////////////////////////////////////////////
0118         /**
0119          * @brief startCapturing Initialize the camera and start capturing
0120          *
0121          * This step calls {@see SequenceJobState::initCapture()}, which triggers
0122          * all actions before the camera may start to capture. If the initialization
0123          * is completed, the sequence job state machine sends the signal
0124          * {@see SequenceJobState::initCaptureComplete()} which will trigger the
0125          * camera device to finally start capturing ({@see capture()}).
0126          *
0127          * @param autofocusReady was there a successful focus run previously?
0128          * @param mode what is the purpose of capturing?
0129          */
0130         void startCapturing(bool autofocusReady, FITSMode mode);
0131         /**
0132          * @brief capture As soon as everything is ready for the camera to start
0133          * capturing, this method triggers the camera device to start capturing.
0134          * @param mode what is the purpose of capturing?
0135          */
0136         void capture(FITSMode mode);
0137         void abort();
0138         void done();
0139 
0140         ////////////////////////////////////////////////////////////////////////
0141         /// Core Properties
0142         ////////////////////////////////////////////////////////////////////////
0143         void setCoreProperty(PropertyID id, const QVariant &value);
0144         QVariant getCoreProperty(PropertyID id) const;
0145 
0146         ////////////////////////////////////////////////////////////////////////
0147         /// Job Status Functions
0148         ////////////////////////////////////////////////////////////////////////
0149         const QString &getStatusString()
0150         {
0151             return StatusStrings()[getStatus()];
0152         }
0153         // Setter: Set how many captures have completed thus far
0154         void setCompleted(int value)
0155         {
0156             m_Completed = value;
0157         }
0158         // Getter: How many captured have completed thus far.
0159         int getCompleted() const
0160         {
0161             return m_Completed;
0162         }
0163         // Setter: Set how many more seconds to expose in this job
0164         void setExposeLeft(double value);
0165         // Getter: Get how many more seconds are left to expose.
0166         double getExposeLeft() const;
0167         // Reset: Reset the job status
0168         void resetStatus(JOBStatus status = JOB_IDLE);
0169         // Setter: Set how many times we re-try this job.
0170         void setCaptureRetires(int value);
0171         // Getter: Get many timed we retried this job already.
0172         int getCaptureRetires() const;
0173         // Getter: How many more seconds are remaining in this job given the
0174         // estimated download time.
0175         int getJobRemainingTime(double estimatedDownloadTime);
0176 
0177         ////////////////////////////////////////////////////////////////////////
0178         /// State Machine Functions
0179         ////////////////////////////////////////////////////////////////////////
0180         // Create all event connections between the state machine and the command processor
0181         void connectDeviceAdaptor();
0182         // Disconnect all event connections between the state machine and the command processor
0183         void disconnectDeviceAdaptor();
0184         // Setter: Set Target Filter Name
0185         void setTargetFilter(int pos, const QString &name);
0186         // Getter: Get Current Filter Slot
0187         int getCurrentFilter() const;
0188         // Retrieve the pier side from the state
0189         ISD::Mount::PierSide getPierSide() const;
0190 
0191         ////////////////////////////////////////////////////////////////////////
0192         /// Job Attribute Functions
0193         ////////////////////////////////////////////////////////////////////////
0194         // job type
0195         SequenceJobType jobType() const
0196         {
0197             return m_jobType;
0198         }
0199         void setJobType(SequenceJobType newJobType)
0200         {
0201             m_jobType = newJobType;
0202         }
0203         QString getSignature()
0204         {
0205             return (getCoreProperty(SJ_Signature).toString()).remove(".fits");
0206         }
0207         // Scripts
0208         const QMap<ScriptTypes, QString> &getScripts() const
0209         {
0210             return m_Scripts;
0211         }
0212         void setScripts(const QMap<ScriptTypes, QString> &scripts)
0213         {
0214             m_Scripts = scripts;
0215         }
0216         const QString getScript(ScriptTypes type) const
0217         {
0218             return m_Scripts[type];
0219         }
0220         void setScript(ScriptTypes type, const QString &value)
0221         {
0222             m_Scripts[type] = value;
0223         }
0224 
0225         // helper function setting both ISO index and ISO value
0226         void setISO(int index);
0227 
0228         // Custom Properties
0229         const QMap<QString, QMap<QString, QVariant> > getCustomProperties() const
0230         {
0231             return m_CustomProperties;
0232         }
0233         void setCustomProperties(const QMap<QString, QMap<QString, QVariant> > &value)
0234         {
0235             m_CustomProperties = value;
0236         }
0237 
0238         // Setter: Set upload mode
0239         void setUploadMode(ISD::Camera::UploadMode value);
0240         // Getter: get upload mode
0241         ISD::Camera::UploadMode getUploadMode() const;
0242 
0243         // Setter: Set flat field source
0244         void setCalibrationPreAction(uint32_t value);
0245         // Getter: Get flat field source
0246         uint32_t getCalibrationPreAction() const;
0247 
0248         // Setter: Set Wall SkyPoint Azimuth coords
0249         void setWallCoord(const SkyPoint &value);
0250         // Getter: Get Flat field source wall coords
0251         const SkyPoint &getWallCoord() const;
0252 
0253         // Setter: Set flat field duration
0254         void setFlatFieldDuration(FlatFieldDuration value);
0255         // Getter: Get flat field duration
0256         FlatFieldDuration getFlatFieldDuration() const;
0257 
0258         // Setter: Set job progress ignored flag
0259         void setJobProgressIgnored(bool value);
0260         bool getJobProgressIgnored() const;
0261 
0262         /**
0263          * @brief updateDeviceStates Update for all used device types whether there
0264          * is one connected.
0265          */
0266         void updateDeviceStates();
0267         /**
0268          * @brief Set the light box device
0269          */
0270         void setLightBox(ISD::LightBox *lightBox);
0271 
0272         /**
0273          * @brief Set the dust cap device
0274          */
0275         void setDustCap(ISD::DustCap *dustCap);
0276 
0277         /**
0278          * @brief Set the telescope device
0279          */
0280         void addMount(ISD::Mount *scope);
0281 
0282         /**
0283          * @brief Set the dome device
0284          */
0285         void setDome(ISD::Dome *dome);
0286 
0287 
0288         // ////////////////////////////////////////////////////////////////////////////
0289         // Facade to state machine
0290         // ////////////////////////////////////////////////////////////////////////////
0291         /**
0292          * @brief Retrieve the current status of the capture sequence job from the state machine
0293          */
0294         JOBStatus getStatus()
0295         {
0296             return state->getStatus();
0297         }
0298 
0299         void setFrameType(CCDFrameType value)
0300         {
0301             state->setFrameType(value);
0302         }
0303         CCDFrameType getFrameType() const
0304         {
0305             return state->getFrameType();
0306         }
0307 
0308         int getTargetFilter() const
0309         {
0310             return state->targetFilterID;
0311         }
0312 
0313         double getTargetTemperature() const
0314         {
0315             return state->targetTemperature;
0316         }
0317         void setTargetTemperature(double value)
0318         {
0319             state->targetTemperature = value;
0320         }
0321 
0322         void setFocusStatus(FocusState value)
0323         {
0324             state->setFocusStatus(value);
0325         }
0326 
0327         double getTargetRotation() const
0328         {
0329             return state->targetPositionAngle;
0330         }
0331         void setTargetRotation(double value)
0332         {
0333             state->targetPositionAngle = value;
0334         }
0335 
0336         SequenceJobState::CalibrationStage getCalibrationStage() const
0337         {
0338             return state->calibrationStage;
0339         }
0340         void setCalibrationStage(SequenceJobState::CalibrationStage value)
0341         {
0342             state->calibrationStage = value;
0343         }
0344 
0345         SequenceJobState::PreparationState getPreparationState() const
0346         {
0347             return state->m_PreparationState;
0348         }
0349         void setPreparationState(SequenceJobState::PreparationState value)
0350         {
0351             state->m_PreparationState = value;
0352         }
0353 
0354         bool getAutoFocusReady() const
0355         {
0356             return state->autoFocusReady;
0357         }
0358         void setAutoFocusReady(bool value)
0359         {
0360             state->autoFocusReady = value;
0361         }
0362 
0363         /**
0364          * @brief Central entry point to start all activities that are necessary
0365          *        before capturing may start. Signals {@see prepareComplete()} as soon as
0366          *        everything is ready.
0367          */
0368         void prepareCapture();
0369         /**
0370          * @brief processPrepareComplete All preparations necessary for capturing are completed
0371          * @param success true iff preparation succeeded
0372          */
0373         void processPrepareComplete(bool success = true);
0374         /**
0375          * @brief Abort capturing
0376          */
0377         void processAbortCapture();
0378 
0379         /**
0380          * @brief Check if all initial tasks are completed so that capturing
0381          *        of flats may start.
0382          * @return IPS_OK if cap is closed, IPS_BUSY if not and IPS_ALERT if the
0383          *         process should be aborted.
0384          */
0385         IPState checkFlatFramePendingTasksCompleted();
0386 
0387         // current values
0388         double currentTemperature() const;
0389         double currentGain() const;
0390         double currentOffset() const;
0391 
0392         void saveTo(QTextStream &outstream, const QLocale &cLocale) const;
0393         void loadFrom(XMLEle *root, const QString &targetName, SequenceJobType jobType,
0394                       QSharedPointer<CaptureModuleState> sharedState);
0395 
0396     signals:
0397         // All preparations necessary for capturing are completed
0398         void prepareComplete(bool success = true);
0399         // Manage the result when capturing has been started
0400         void captureStarted(CaptureModuleState::CAPTUREResult rc);
0401         // Abort capturing
0402         void abortCapture();
0403         // log entry
0404         void newLog(QString);
0405 
0406         void prepareState(CaptureState state);
0407         // signals to be forwarded to the state machine
0408         void prepareCapture(CCDFrameType frameType, bool enforceCCDTemp, bool enforceStartGuiderDrift, bool isPreview);
0409         // update the current guiding deviation
0410         void updateGuiderDrift(double deviation_rms);
0411 
0412 private:
0413         /**
0414          * @brief init Initialize the sequence job from its XML representation
0415          */
0416         void init(SequenceJobType jobType, XMLEle *root, QSharedPointer<CaptureModuleState> sharedState, const QString &targetName);
0417 
0418         // job type (batch, preview, ...)
0419         SequenceJobType m_jobType;
0420 
0421         void setStatus(JOBStatus const);
0422 
0423         //////////////////////////////////////////////////////////////
0424         /// Custom Types
0425         /// We save all core sequence properties in QVariant map
0426         //////////////////////////////////////////////////////////////
0427         QMap<PropertyID, QVariant> m_CoreProperties;
0428 
0429         //////////////////////////////////////////////////////////////
0430         /// Custom Types
0431         /// We don't use Q_PROPERTY for these to simplify use
0432         //////////////////////////////////////////////////////////////
0433         QMap<QString, QMap<QString, QVariant>> m_CustomProperties;
0434         FlatFieldDuration m_FlatFieldDuration { DURATION_MANUAL };
0435         // Capture Scripts
0436         QMap<ScriptTypes, QString> m_Scripts;
0437         // Upload Mode
0438         ISD::Camera::UploadMode m_UploadMode { ISD::Camera::UPLOAD_CLIENT };
0439         // Transfer Format
0440         QString m_TransferFormat { "FITS" };
0441 
0442         //////////////////////////////////////////////////////////////
0443         /// Status Variables
0444         //////////////////////////////////////////////////////////////
0445         int m_CaptureRetires { 0 };
0446         uint32_t m_Completed { 0 };
0447         double m_ExposeLeft { 0 };
0448         bool m_JobProgressIgnored {false};
0449 
0450         //////////////////////////////////////////////////////////////
0451         /// Device access
0452         //////////////////////////////////////////////////////////////
0453 
0454         /**
0455          * @brief frameTypes Retrieve the frame types from the active camera's primary chip.
0456          */
0457         QStringList frameTypes() const;
0458         /**
0459          * @brief filterLabels list of currently available filter labels
0460          */
0461         QStringList filterLabels() const;
0462 
0463         //////////////////////////////////////////////////////////////
0464         /// State machines encapsulating the state of this capture sequence job
0465         //////////////////////////////////////////////////////////////
0466         QSharedPointer<CaptureDeviceAdaptor> devices;
0467         QSharedPointer<SequenceJobState> state;
0468 };
0469 
0470 }