File indexing completed on 2024-04-21 14:46:05

0001 /*
0002     SPDX-FileCopyrightText: 2012-2022 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QString>
0010 #include <QMap>
0011 #include <chrono>
0012 /*!
0013 \page INDI "INDI Overview"
0014 \tableofcontents
0015 
0016 \section Intro Introduction
0017 
0018 INDI is a simple XML-like communications protocol described for interactive and automated remote control of diverse instrumentation. INDI is small, easy to parse, and stateless.
0019 The main key concept in INDI is that devices have the ability to describe themselves. This is accomplished by using XML to describe a generic hierarchy that can represent both canonical and
0020  non-canonical devices. All devices may contain one or more properties. A property in the INDI paradigm describes a specific function of the driver.
0021 Any property may contain one or more elements. There are four types of INDI properties:
0022 
0023 <ul>
0024 <li><b>Text property</b>: Property to transfer simple text information in ISO-8859-1. The text is not encoded or encrypted on transfer. If the text includes elements that can break XML syntax, a BLOB property should be used to make the transfer.</li>
0025 <li><b>Number property</b>: Property to transfer numeric information with configurable minimum, maximum, and step values. The supported number formats are decimal and sexigesmal. The property includes a GUI hint element in printf style format to enable clients to properly display numeric properties.</li>
0026 <li><b>Switch property</b>: Property to hold a group of options or selections (Represented in GUI by buttons and check boxes).</li>
0027 <li><b>Light property</b>: Property to hold a group of status indicators (Represented in GUI by colored LEDs).</li>
0028 <li><b>BLOB property</b>: BLOB is a Binary Large OBject used to transfer binary data to and from drivers.</li>
0029 </ul>
0030 
0031 For example, all INDI devices share the CONNECTION standard switch property. The CONNECTION property has two elements: CONNECT and DISCONNECT switches.
0032 GUI clients parse the generic XML description of properties and builds a GUI representation suitable for direct human interaction.
0033 
0034 KStars is a fully featured INDI client. INDI Data (i.e. devices and properties) and GUI (how they appear on the screen) are separated. INDI adopts is a server/client architecture where one or more servers
0035 communicate with one or more drivers, each driver can communicate with one or more actual hardware devices. Clients connect to the server, obtain a list of devices, and generate GUI to represent the
0036 devices for user interaction and control. The creation of GUI happens in run time via introspection.
0037 
0038 \section Structure Hierarchy
0039 
0040 The following is a description of some of the various classes that support INDI:
0041 
0042 <ul>
0043 <li>DriverManager: Manages local drivers as installed by INDI library. Enables users to start/stop local INDI servers (ServerManager) running one or more drivers (DriverInfo). Also enables connecting to local or remote
0044 INDI servers. For both local and remote connection, it creates a ClientManager to handle incoming data from each INDI server started, and creates a GUIManager to render the devices in INDI Control Panel.
0045 The user may also choose to only start an INDI server without a client manager and GUI.</li>
0046 <li>ClientManager: Manages sending and receiving data from and to an INDI server. The ClientManager sends notifications (signals) when a new device or property is defined, updated, or deleted.</li>
0047 <li>GUIManager: Handles creation of GUI interface for devices (INDI_D) and their properties and updates the interface in accord with any data emitted by the associated ClientManager. The GUI manager supports
0048 multiple ClientManagers and consolidate all devices from all the ClientManagers into a single INDI Control Panel where each device is created as a tab.</li>
0049 <li>INDIListener: Once a ClientManager is created in DriverManager after successfully connecting to an INDI server, it is added to INDIListener which creates an ISD::Generic device instance for each and passes down any property events to the device instance.</li>
0050 <li>ServerManager</li> Manages establishment and shutdown of local INDI servers.</li>
0051 <li>DriverInfo</li>: Simple class that holds information on INDI drivers such as name, version, device type..etc.</li>
0052 <li>ISD::GDInterface: Abstract class where the ISD::GenericDevice and ISD::ConcreteDevice are derived.</li>
0053 <li>ISD::GenericDevice: Base class for all INDI devices. It implements processes shared across all INDI devices such as handling connection/disconnection, setting of configuration..etc.. When a
0054 After properties are defined, it checks the driver interface and defined a device subtype using ISD::ConcreteDevice for each subtype.</li>
0055 <li>ISD::ConcreteDevice: Base class for concrete device implementations such as ISD::Mount and ISD::Camera. The parent class ISD::GenericDevice passes property events down to the ConcreteDevice class so it may
0056 process the properties relevant to this device type. For example, ISD::Mount would process EOD_EQUATORIAL_EOD coord property while ISD::Camera would process CCD_EXPOSURE property..etc.</li>
0057 </ul>
0058 
0059 \section Example Example
0060 
0061 Suppose the user wishes to control an EQMod mount with \e indi_eqmod_telescope driver. From the DriverManager GUI, the user selects the driver and \e starts INDI services. The DriverManager
0062 will create a ServerManager instance to run an INDI server with the EQMod driver executable. After establishing the server, the DriverManager will create an instance of ClientManager and set
0063 its INDI server address as the host and port of the server created in ServerManager. For local servers, the host name is \e localhost and the default INDI port is 7624. If connection to the INDI server
0064 is successful, DriverManager then adds the ClientManager to both INDIListener (to handle data), and GUIManager (to handle GUI). Since the ClientManager emits signals whenever a new, updated, or deleted
0065 device/property is received from INDI server, it affects both the data handling part as well as GUI rendering.
0066 
0067 INDIListener holds a list of all INDI devices in KStars regardless of their origin. Once INDIListener receives a new device from the ClientManager, it creates a new ISD::GenericDevice. At the GUIManager side, it creates INDI Control Panel and adds a new tab with the device name.
0068 It also creates a separate tab for each property group received. The user is presented with a basic GUI to set the connection port of EQMod and to connect/disconnect to/from the telescope. If the
0069 user clicks connect, the status of the connection property is updated, and INDI_P sends the new switch status (CONNECT=ON) to INDI server via the ClientManager. If the connection is successful
0070 at the driver side, it will start defining new properties to cover the complete functionality of the EQMod driver, one of the standard properties is EQUATORIAL_EOD_COORD which will be detected
0071 in INDIListener. Upon detection of this key signature property, INDIListener creates a new ISD::Mount device while passing to it the ISD::GenericDevice instance created earlier.
0072 
0073 Now suppose an updated Number property arrives from INDI server, the ClientManager emits a signal indicating a number property has a new updated value and INDIListener delegates the INDI Number
0074 property to the device, which is now of type ISD::Mount. The ISD::Mount overridden the processNumber(INumberVectorProperty *nvp) function in ISD::DeviceDecorator because it wants to handle some telescope
0075 specific numbers such as EQUATORIAL_EOD_COORD in order to move the telescope marker on the sky map as it changes. If the received property was indeed EQUATORIAL_EOD_COORD or any property handled
0076 by the ISD::Mount ProcessNumber() function, then there is no further action needed. But what if the property is not processed in ISD::Mount ProcessNumber() function? In this case, the
0077 ProcessNumber() function simply calls DeviceDecorator::ProcessNumber() and it will delgate the call to ISD::GenericDevice ProcessNumber() to process. This is how the Decorator pattern work,
0078 the decorator classes implements extended functionality, but the basic class is still responsible for handling all of the basic functions.
0079 
0080 */
0081 
0082 #define INDIVERSION 1.7 /* we support this or less */
0083 
0084 typedef enum { PRIMARY_XML, THIRD_PARTY_XML, EM_XML, HOST_SOURCE, CUSTOM_SOURCE, GENERATED_SOURCE } DriverSource;
0085 
0086 typedef enum { SERVER_CLIENT, SERVER_ONLY } ServerMode;
0087 
0088 typedef enum { DATA_FITS, DATA_VIDEO, DATA_CCDPREVIEW, DATA_ASCII, DATA_OTHER } INDIDataTypes;
0089 
0090 typedef enum { LOAD_LAST_CONFIG, SAVE_CONFIG, LOAD_DEFAULT_CONFIG, PURGE_CONFIG } INDIConfig;
0091 
0092 typedef enum { NO_DIR = 0, RA_INC_DIR, RA_DEC_DIR, DEC_INC_DIR, DEC_DEC_DIR } GuideDirection;
0093 
0094 /* GUI layout */
0095 #define PROPERTY_LABEL_WIDTH 130
0096 #define PROPERTY_LABEL_HEIGHT 30
0097 #define ELEMENT_LABEL_WIDTH  175
0098 #define ELEMENT_LABEL_HEIGHT 30
0099 #define ELEMENT_READ_WIDTH   175
0100 #define ELEMENT_WRITE_WIDTH  175
0101 #define ELEMENT_FULL_WIDTH   340
0102 #define MIN_SET_WIDTH        50
0103 #define MAX_SET_WIDTH        110
0104 #define MED_INDI_FONT        2
0105 #define MAX_LABEL_LENGTH     20
0106 
0107 typedef enum { PG_NONE = 0, PG_TEXT, PG_NUMERIC, PG_BUTTONS, PG_RADIO, PG_MENU, PG_LIGHTS, PG_BLOB } PGui;
0108 
0109 /* new versions of glibc define TIME_UTC as a macro */
0110 #undef TIME_UTC
0111 
0112 /* Devices families that we explicitly support (i.e. with std properties) */
0113 typedef enum
0114 {
0115     KSTARS_ADAPTIVE_OPTICS,
0116     KSTARS_AGENT,
0117     KSTARS_AUXILIARY,
0118     KSTARS_CCD,
0119     KSTARS_DETECTORS,
0120     KSTARS_DOME,
0121     KSTARS_FILTER,
0122     KSTARS_FOCUSER,
0123     KSTARS_ROTATOR,
0124     KSTARS_SPECTROGRAPHS,
0125     KSTARS_TELESCOPE,
0126     KSTARS_WEATHER,
0127     KSTARS_UNKNOWN
0128 } DeviceFamily;
0129 
0130 const QMap<DeviceFamily, QString> DeviceFamilyLabels =
0131 {
0132     {KSTARS_ADAPTIVE_OPTICS, "Adaptive Optics"},
0133     {KSTARS_AGENT, "Agent"},
0134     {KSTARS_AUXILIARY, "Auxiliary"},
0135     {KSTARS_CCD, "CCDs"},
0136     {KSTARS_DETECTORS, "Detectors"},
0137     {KSTARS_DOME, "Domes"},
0138     {KSTARS_FILTER, "Filter Wheels"},
0139     {KSTARS_FOCUSER, "Focusers"},
0140     {KSTARS_ROTATOR, "Rotators"},
0141     {KSTARS_SPECTROGRAPHS, "Spectrographs"},
0142     {KSTARS_TELESCOPE, "Telescopes"},
0143     {KSTARS_WEATHER, "Weather"},
0144     {KSTARS_UNKNOWN, "Unknown"},
0145 };
0146 
0147 typedef enum { FRAME_LIGHT, FRAME_BIAS, FRAME_DARK, FRAME_FLAT, FRAME_NONE } CCDFrameType;
0148 
0149 const QMap<CCDFrameType, QString> CCDFrameTypeNames =
0150 {
0151     {FRAME_LIGHT, "Light"},
0152     {FRAME_DARK, "Dark"},
0153     {FRAME_BIAS, "Bias"},
0154     {FRAME_FLAT, "Flat"},
0155     {FRAME_NONE, ""},
0156 };
0157 
0158 
0159 typedef enum { SINGLE_BIN, DOUBLE_BIN, TRIPLE_BIN, QUADRAPLE_BIN } CCDBinType;
0160 
0161 typedef enum {
0162     ACTION_NONE       = 1 << 0,
0163     ACTION_WALL       = 1 << 1,
0164     ACTION_PARK_MOUNT = 1 << 2,
0165     ACTION_PARK_DOME  = 1 << 3,
0166 } CalibrationPreActions;
0167 
0168 typedef enum { DURATION_MANUAL, DURATION_ADU } FlatFieldDuration;
0169 
0170 using Seconds = std::chrono::duration<double>;