Implementing the Dome Interface
This guide provides a comprehensive overview of implementing the Dome Interface in INDI drivers. It covers the extensive functionality for controlling astronomical domes, including absolute and relative movement, parking, shutter control, slaving to a mount, and various status reporting mechanisms.
Introduction to the Dome Interface
The INDI Dome Interface (INDI::Dome) provides a robust framework for controlling observatory domes. It supports both relative and absolute position domes, and even open-loop control for domes without position feedback, using simple direction commands (Clockwise and Counter-Clockwise).
A key feature is slaving, which synchronizes the dome’s azimuth position with that of an active mount. This involves snooping mount coordinates and initiating dome motion when the mount slews or its tracking position exceeds a configurable AutoSync threshold. Custom parking positions are also supported for absolute/relative domes, and for roll-off observatories, the parking state reflects the roof’s open/closed status.
Developers need to subclass INDI::Dome to implement any driver for Domes within INDI.
IMPORTANT: Before using any of the dome functions, you must define the capabilities of the dome by calling SetDomeCapability() function.
Prerequisites
Before implementing the Dome Interface, you should have:
- Basic knowledge of C++ programming
- Understanding of the INDI protocol and architecture
- Familiarity with the device’s communication protocol
- Development environment set up (compiler, build tools, etc.)
- INDI library installed
Dome Interface Structure
The Dome Interface is a comprehensive class that provides general functionality for a Dome device. It includes mechanisms for motion control, status reporting, configuration, and advanced features like slaving and geometric calculations.
Base Class
The INDI::Dome class inherits from INDI::DefaultDevice and provides a wide array of functionalities specific to dome control.
Enums and Typedefs
The interface defines several enums and typedefs to manage dome operations and states:
DomeMeasurements
Measurements necessary for dome-slit synchronization. All values are in meters. The displacements are measured from the true dome center, and the dome is assumed spherical.
typedef enum
{
DM_DOME_RADIUS, /*!< Dome RADIUS */
DM_SHUTTER_WIDTH, /*!< Shutter width */
DM_NORTH_DISPLACEMENT, /*!< Displacement to north of the mount center */
DM_EAST_DISPLACEMENT, /*!< Displacement to east of the mount center */
DM_UP_DISPLACEMENT, /*!< Up Displacement of the mount center */
DM_OTA_OFFSET /*!< Distance from the optical axis to the mount center*/
} DomeMeasurements;
DM_DOME_RADIUS: The radius of the dome.DM_SHUTTER_WIDTH: The width of the dome’s shutter aperture.DM_NORTH_DISPLACEMENT: Displacement of the mount center to the north from the true dome center.DM_EAST_DISPLACEMENT: Displacement of the mount center to the east from the true dome center.DM_UP_DISPLACEMENT: Upward displacement of the mount center from the true dome center.DM_OTA_OFFSET: Distance from the optical axis of the telescope to the mount center.
DomeDirection
Defines the direction of dome motion.
enum DomeDirection
{
DOME_CW, /*!< Clockwise direction */
DOME_CCW /*!< Counter-clockwise direction */
};
DomeMotionCommand
Defines commands for dome motion.
enum DomeMotionCommand
{
MOTION_START, /*!< Start motion */
MOTION_STOP /*!< Stop motion */
};
DomeParkData
Defines the type of parking data supported by the dome.
enum DomeParkData
{
PARK_NONE, /*!< 2-state parking (Open or Closed only) */
PARK_AZ, /*!< Parking via azimuth angle control */
PARK_AZ_ENCODER, /*!< Parking via azimuth encoder control */
};
ShutterOperation
Defines commands for shutter operation.
typedef enum
{
SHUTTER_OPEN, /*!< Open Shutter */
SHUTTER_CLOSE /*!< Close Shutter */
} ShutterOperation;
MountLockingPolicy
Defines how the dome interacts with the mount’s parking status.
enum MountLockingPolicy
{
MOUNT_IGNORED, /*!< Mount is ignored. Dome can park or unpark irrespective of mount parking status */
MOUNT_LOCKS, /*!< Mount Locks. Dome can park if mount is completely parked first. */
};
DomeState
Defines the possible states of the dome.
typedef enum
{
DOME_IDLE, /*!< Dome is idle */
DOME_MOVING, /*!< Dome is in motion */
DOME_SYNCED, /*!< Dome is synced */
DOME_PARKING, /*!< Dome is parking */
DOME_UNPARKING, /*!< Dome is unparking */
DOME_PARKED, /*!< Dome is parked */
DOME_UNPARKED, /*!< Dome is unparked */
DOME_UNKNOWN, /*!< Dome state is known */
DOME_ERROR, /*!< Dome has errors */
} DomeState;
ShutterState
Defines the possible states of the shutter.
typedef enum
{
SHUTTER_OPENED, /*!< Shutter is open */
SHUTTER_CLOSED, /*!< Shutter is closed */
SHUTTER_MOVING, /*!< Shutter in motion (opening or closing) */
SHUTTER_UNKNOWN, /*!< Shutter status is unknown */
SHUTTER_ERROR /*!< Shutter status is unknown */
} ShutterState;
Dome Capabilities
These flags define the capabilities of the dome, which must be set using SetDomeCapability().
enum
{
DOME_CAN_ABORT = 1 << 0, /*!< Can the dome motion be aborted? */
DOME_CAN_ABS_MOVE = 1 << 1, /*!< Can the dome move to an absolute azimuth position? */
DOME_CAN_REL_MOVE = 1 << 2, /*!< Can the dome move to a relative position a number of degrees away from current position? Positive degrees is Clockwise direction. Negative Degrees is counter clock wise direction */
DOME_CAN_PARK = 1 << 3, /*!< Can the dome park and unpark itself? */
DOME_CAN_SYNC = 1 << 4, /*!< Can the dome sync to arbitrary position? */
DOME_HAS_SHUTTER = 1 << 5, /*!< Does the dome has a shutter than can be opened and closed electronically? */
DOME_HAS_VARIABLE_SPEED = 1 << 6, /*!< Can the dome move in different configurable speeds? */
DOME_HAS_BACKLASH = 1 << 7 /*!< Can the dome compensate for backlash? */
};
DomeConnection
Defines the connection mode of the Dome.
enum
{
CONNECTION_NONE = 1 << 0, /** Do not use any connection plugin */
CONNECTION_SERIAL = 1 << 1, /** For regular serial and bluetooth connections */
CONNECTION_TCP = 1 << 2 /** For Wired and WiFI connections */
} DomeConnection;
Key Methods (Public)
The INDI::Dome class provides the following public methods:
-
Dome();Constructor for theINDI::Domeclass. -
virtual ~Dome();Destructor for theINDI::Domeclass. -
virtual bool initProperties() override;Initializes the INDI properties for the dome. This should be called within the driver’sinitProperties()method. -
virtual void ISGetProperties(const char * dev) override;Handles client requests to get properties. -
virtual bool updateProperties() override;Defines or deletes dome properties based on the connection status of the device. -
virtual bool ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) override;Processes incoming client requests for number properties. -
virtual bool ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n) override;Processes incoming client requests for switch properties. -
virtual bool ISNewText(const char * dev, const char * name, char * texts[], char * names[], int n) override;Processes incoming client requests for text properties. -
virtual bool ISSnoopDevice(XMLEle * root) override;Handles snooping of properties from other devices (e.g., mount coordinates for slaving). -
static void buttonHelper(const char * button_n, ISState state, void * context);A helper function for handling button presses. -
void setDomeConnection(const uint8_t &value);Sets the dome connection mode (e.g., serial, TCP). Should be called in the child class constructor. -
uint8_t getDomeConnection() const;Returns the current dome connection mode. -
uint32_t GetDomeCapability() const;Returns the capabilities of the dome as a bitmask. -
void SetDomeCapability(uint32_t cap);Sets the capabilities of the dome. This must be called before using other dome functions. -
bool CanAbort();Returnstrueif the dome supports aborting motion. -
bool CanAbsMove();Returnstrueif the dome supports moving to an absolute azimuth position. -
bool CanRelMove();Returnstrueif the dome supports moving to a relative position. -
bool CanPark();Returnstrueif the dome supports parking and unparking. -
bool CanSync();Returnstrueif the dome supports syncing to an arbitrary position. -
bool HasShutter();Returnstrueif the dome has an electronically controllable shutter. -
bool HasVariableSpeed();Returnstrueif the dome supports different configurable speeds. -
bool HasBacklash();Returnstrueif the dome supports backlash compensation. -
bool isLocked();Checks if the dome is currently locked (e.g., due to mount parking policy). -
DomeState getDomeState() const;Returns the current state of the dome. -
void setDomeState(const DomeState &value);Sets the current state of the dome. -
ShutterState getShutterState() const;Returns the current state of the shutter. -
void setShutterState(const ShutterState &value);Sets the current state of the shutter. -
IPState getMountState() const;Returns the current state of the mount (snooped).
Key Methods (Protected Virtual)
These methods are intended to be overridden by the child driver class to implement specific hardware control.
virtual bool SetSpeed(double rpm);Sets the dome’s rotation speed. This does not initiate motion.rpm: Desired speed in RPM.- Returns
trueif successful,falseotherwise.
virtual IPState Move(DomeDirection dir, DomeMotionCommand operation);Moves the dome in a specified direction (clockwise or counter-clockwise).dir: Direction of motion (DOME_CWorDOME_CCW).operation: Command (MOTION_STARTorMOTION_STOP).- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
virtual IPState MoveAbs(double az);Moves the dome to an absolute azimuth position.az: Target azimuth in degrees.- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
virtual IPState MoveRel(double azDiff);Moves the dome by a relative azimuth difference.azDiff: Relative azimuth angle in degrees (positive for CW, negative for CCW).- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
virtual bool Sync(double az);Synchronizes the dome’s current azimuth to a given azimuth position.az: Target azimuth in degrees.- Returns
trueif successful,falseotherwise.
virtual bool Abort();Aborts all dome motion.- Returns
trueif successful,falseotherwise.
- Returns
virtual IPState Park();Commands the dome to its park position.- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
- Returns
virtual IPState UnPark();Commands the dome to unpark. This action is dome-specific and may include opening the shutter and moving to a home position.- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
- Returns
virtual bool SetBacklash(int32_t steps);Sets the dome backlash compensation value.steps: Value in absolute steps to compensate.- Returns
trueif successful,falseotherwise.
virtual bool SetBacklashEnabled(bool enabled);Enables or disables dome backlash compensation.enabled:trueto enable,falseto disable.- Returns
trueif successful,falseotherwise.
virtual IPState ControlShutter(ShutterOperation operation);Opens or closes the dome shutter.operation:SHUTTER_OPENorSHUTTER_CLOSE.- Returns
IPS_OKif complete,IPS_BUSYif in progress,IPS_ALERTon error.
-
const char * GetShutterStatusString(ShutterState status);Returns a string representation of the shutter status. -
void SetParkDataType(DomeParkData type);Sets the type of parking data (e.g., azimuth angle, encoder values). bool InitPark();Loads parking data from~/.indi/ParkData.xml. Should be called after successful connection.- Returns
trueif successful,falseotherwise.
- Returns
bool isParked();Checks if the dome is currently parked.- Returns
trueif parked,falseotherwise.
- Returns
-
void SetParked(bool isparked);Changes the dome parking status and updates the park data file. -
double GetAxis1Park();Returns the current azimuth parking position. -
double GetAxis1ParkDefault();Returns the default azimuth parking position. -
void SetAxis1Park(double value);Sets the current azimuth parking position. -
void SetAxis1ParkDefault(double steps);Sets the default azimuth parking position. -
virtual bool SetCurrentPark();Sets the current coordinates/encoders value as the desired parking position. (No action unless subclassed). -
virtual bool SetDefaultPark();Sets default coordinates/encoders value as the desired parking position. (No action unless subclassed). -
const char * LoadParkData();Loads parking data from XML. -
bool WriteParkData();Writes parking data to XML. -
bool GetTargetAz(double &Az, double &Alt, double &minAz, double &maxAz);Calculates the required dome azimuth to center the shutter aperture with the telescope. -
bool Intersection(point3D p1, point3D p2, double r, double &mu1, double &mu2);Calculates the intersection of a ray and a sphere (used in geometry calculations). -
bool OpticalCenter(point3D MountCenter, double dOpticalAxis, double Lat, double Ah, point3D &OP);Calculates the distance from the optical axis to the dome center. -
bool OpticalVector(double Az, double Alt, point3D &OV);Calculates a second point for determining the optical axis. -
bool CheckHorizon(double HA, double dec, double lat);Checks if the telescope points above the horizon. -
virtual bool saveConfigItems(FILE * fp) override;Saves device port and dome presets in the configuration file. -
void UpdateMountCoords();Updates the horizontal coordinates (Az & Alt) of the mount from snooped RA, DEC, and observer’s location. -
virtual void UpdateAutoSync();Calculates target dome azimuth from mount’s target coordinates and commands dome motion if the difference exceeds the AutoSync threshold. -
virtual bool Handshake();Performs a handshake with the device to check communication. -
virtual void ActiveDevicesUpdated() {};Signal to concrete driver when Active Devices are updated. -
double Csc(double x);Calculates cosecant. double Sec(double x);Calculates secant.
Member Variables
The INDI::Dome class includes numerous INDI::Property members and other significant variables for managing dome state and configuration:
-
INDI::PropertyNumber DomeSpeedNP;Property for setting and reporting dome speed. -
INDI::PropertySwitch DomeMotionSP;Property for controlling continuous dome motion (CW/CCW, Start/Stop). -
INDI::PropertyNumber DomeAbsPosNP;Property for setting and reporting absolute azimuth position. -
INDI::PropertyNumber DomeRelPosNP;Property for setting and reporting relative azimuth movement. -
INDI::PropertySwitch AbortSP;Property for aborting dome motion. -
INDI::PropertyNumber DomeParamNP;Generic number property for dome parameters. -
INDI::PropertyNumber DomeSyncNP;Property for syncing the dome to a specific azimuth. -
INDI::PropertySwitch DomeShutterSP;Property for controlling the shutter (Open/Close). -
INDI::PropertySwitch ParkSP;Property for parking and unparking the dome. -
INDI::PropertyNumber ParkPositionNP;Property for setting a custom park position. -
INDI::PropertySwitch ParkOptionSP;Property for various parking options. -
INDI::PropertyText ActiveDeviceTP;Property for specifying active devices (Mount, Input, Output) for slaving. -
INDI::PropertySwitch MountPolicySP;Property for defining mount locking policy (ignored, locks). -
INDI::PropertySwitch ShutterParkPolicySP;Property for defining shutter behavior during park/unpark (close on park, open on unpark). -
INDI::PropertyNumber PresetNP;Property for dome presets. -
INDI::PropertySwitch PresetGotoSP;Property for initiating movement to presets. -
INDI::PropertyNumber DomeMeasurementsNP;Property for dome measurement parameters (radius, shutter width, displacements, etc.). -
INDI::PropertySwitch OTASideSP;Property for specifying the side of the OTA (Optical Tube Assembly) relative to the mount. -
INDI::PropertySwitch DomeAutoSyncSP;Property for enabling/disabling and configuring auto-synchronization. -
INDI::PropertySwitch DomeBacklashSP;Property for enabling/disabling backlash compensation. -
INDI::PropertyNumber DomeBacklashNP;Property for setting backlash compensation steps. -
uint32_t capability;Stores the bitmask of dome capabilities. -
DomeParkData parkDataType;Stores the type of parking data. -
DomeState m_DomeState;Current state of the dome. -
ShutterState m_ShutterState;Current state of the shutter. -
IPState m_MountState;Current state of the snooped mount. -
IGeographicCoordinates observer;Observer’s geographic coordinates (snooped from mount). -
bool HaveLatLong;Indicates if valid geographic coordinates are available. -
INDI::IHorizontalCoordinates mountHoriztonalCoords;Mount’s horizontal coordinates (snooped). -
INDI::IEquatorialCoordinates mountEquatorialCoords;Mount’s equatorial coordinates (snooped). -
bool HaveRaDec;Indicates if valid RA/Dec coordinates are available. -
int PortFD;File descriptor for serial/TCP connection. -
Connection::Serial * serialConnection;Pointer to serial connection object. -
Connection::TCP * tcpConnection;Pointer to TCP connection object. -
bool IsParked;Internal flag indicating if the dome is parked. -
bool IsMountParked;Internal flag indicating if the mount is parked. -
bool IsLocked;Internal flag indicating if the dome is locked. -
bool AutoSyncWarning;Internal flag for auto-sync warnings. -
bool UseHourAngle;Internal flag for using hour angle in calculations. -
const char * ParkDeviceName;Name of the device used for parking. -
const std::string ParkDataFileName;File name for parking data. -
INDI::Timer m_MountUpdateTimer;Timer for mount updates. -
XMLEle * ParkdataXmlRoot, *ParkdeviceXml, *ParkstatusXml, *ParkpositionXml, *ParkpositionAxis1Xml;XML elements for parsing parking data. -
double Axis1ParkPosition;Current park position for Axis 1 (Azimuth). -
double Axis1DefaultParkPosition;Default park position for Axis 1 (Azimuth). -
uint8_t domeConnection;Stores the dome connection type.
Example Implementation
Here’s a simplified example of how a driver might implement the INDI::Dome interface, drawing inspiration from the domepro2.cpp driver. This example focuses on the core structure and omits complex serial communication and detailed error handling for clarity.
```cpp
#include “indibase.h”
#include “indidome.h”
#include
// Forward declaration of a dummy DefaultDevice for the example // INDI::Dome already inherits from DefaultDevice, so no need to inherit it again. class MyDomeDevice : public INDI::Dome { public: MyDomeDevice() : INDI::Dome() { // Set dome capabilities in the constructor SetDomeCapability(DOME_CAN_ABORT | DOME_CAN_ABS_MOVE | DOME_CAN_REL_MOVE | DOME_CAN_PARK | DOME_CAN_SYNC | DOME_HAS_SHUTTER);
// Set the driver interface
setDriverInterface(DOME_INTERFACE);
}
virtual const char *getDefaultName() override
{
return "MyDome";
}
virtual bool initProperties() override
{
INDI::Dome::initProperties(); // Call base class initProperties
// Example of defining custom properties if needed, beyond what INDI::Dome provides
// For instance, a property for dome specific settings
// MyCustomDomeSettingNP.fill(...);
// defineProperty(MyCustomDomeSettingNP);
// Initialize parking data
SetParkDataType(PARK_AZ); // This dome parks by azimuth angle
if (InitPark())
{
// If loading parking data is successful, we just set the default parking values.
SetAxis1ParkDefault(0); // Default park azimuth is 0 degrees
}
else
{
// Otherwise, we set all parking data to default in case no parking data is found.
SetAxis1Park(0);
SetAxis1ParkDefault(0);
}
return true;
}
virtual bool updateProperties() override
{
INDI::Dome::updateProperties(); // Call base class updateProperties
if (isConnected())
{
// Define any custom properties here if they depend on connection status
// defineProperty(MyCustomDomeSettingNP);
SetTimer(getCurrentPollingPeriod()); // Start timer for periodic updates
}
else
{
// Delete any custom properties here
// deleteProperty(MyCustomDomeSettingNP);
}
return true;
}
// Implement the crucial virtual methods from INDI::Dome
virtual IPState MoveAbs(double az) override
{
LOGF_INFO("Dome: Moving to absolute azimuth %.2f degrees.", az);
// Simulate hardware action
std::thread([this, az]() {
std::this_thread::sleep_for(std::chrono::seconds(5)); // Simulate motion time
m_currentAzimuth = az; // Update internal state
LOGF_INFO("Dome: Reached absolute azimuth %.2f degrees.", az);
DomeAbsPosNP[0].setValue(m_currentAzimuth);
DomeAbsPosNP.setState(IPS_OK);
IDSetNumber(&DomeAbsPosNP, nullptr); // Notify clients
setDomeState(DOME_IDLE);
}).detach();
setDomeState(DOME_MOVING);
DomeAbsPosNP.setState(IPS_BUSY);
IDSetNumber(&DomeAbsPosNP, nullptr);
return IPS_BUSY;
}
virtual IPState MoveRel(double azDiff) override
{
double targetAz = m_currentAzimuth + azDiff;
// Handle wrap-around for azimuth (0-360 degrees)
if (targetAz < 0) targetAz += 360;
if (targetAz >= 360) targetAz -= 360;
LOGF_INFO("Dome: Moving relative by %.2f degrees to target %.2f.", azDiff, targetAz);
return MoveAbs(targetAz); // Delegate to MoveAbs
}
virtual bool Sync(double az) override
{
LOGF_INFO("Dome: Syncing current azimuth to %.2f degrees.", az);
m_currentAzimuth = az; // Instantly sync in simulation
DomeAbsPosNP[0].setValue(m_currentAzimuth);
DomeAbsPosNP.setState(IPS_OK);
IDSetNumber(&DomeAbsPosNP, nullptr);
setDomeState(DOME_SYNCED);
return true;
}
virtual IPState Abort() override
{
LOG_INFO("Dome: Aborting motion.");
// In a real driver, send an abort command to hardware.
// For simulation, just set state to ALERT and IDLE.
DomeAbsPosNP.setState(IPS_ALERT);
IDSetNumber(&DomeAbsPosNP, nullptr);
setDomeState(DOME_IDLE);
setShutterState(SHUTTER_UNKNOWN); // Shutter state might be unknown after abort
return IPS_OK;
}
virtual IPState Park() override
{
LOG_INFO("Dome: Parking (moving to park position and closing shutter).");
// Simulate parking sequence
std::thread([this]() {
// Move to park azimuth
std::this_thread::sleep_for(std::chrono::seconds(5));
m_currentAzimuth = GetAxis1Park(); // Get the configured park azimuth
DomeAbsPosNP[0].setValue(m_currentAzimuth);
DomeAbsPosNP.setState(IPS_OK);
IDSetNumber(&DomeAbsPosNP, nullptr);
LOGF_INFO("Dome: Reached park azimuth %.2f degrees.", m_currentAzimuth);
// Close shutter
std::this_thread::sleep_for(std::chrono::seconds(3));
m_isShutterOpen = false;
LOG_INFO("Dome: Shutter closed.");
setShutterState(SHUTTER_CLOSED);
SetParked(true); // Mark as parked
setDomeState(DOME_PARKED);
ParkSP.setState(IPS_OK);
IDSetSwitch(&ParkSP, nullptr);
}).detach();
setDomeState(DOME_PARKING);
ParkSP.setState(IPS_BUSY);
IDSetSwitch(&ParkSP, nullptr);
return IPS_BUSY;
}
virtual IPState UnPark() override
{
LOG_INFO("Dome: Unparking (opening shutter and moving to home position).");
// Simulate unparking sequence
std::thread([this]() {
// Open shutter
std::this_thread::sleep_for(std::chrono::seconds(3));
m_isShutterOpen = true;
LOG_INFO("Dome: Shutter opened.");
setShutterState(SHUTTER_OPENED);
// Move to a default unpark/home azimuth (e.g., 0 degrees)
std::this_thread::sleep_for(std::chrono::seconds(5));
m_currentAzimuth = 0; // Example home position
DomeAbsPosNP[0].setValue(m_currentAzimuth);
DomeAbsPosNP.setState(IPS_OK);
IDSetNumber(&DomeAbsPosNP, nullptr);
LOGF_INFO("Dome: Reached unpark/home azimuth %.2f degrees.", m_currentAzimuth);
SetParked(false); // Mark as unparked
setDomeState(DOME_UNPARKED);
ParkSP.setState(IPS_OK);
IDSetSwitch(&ParkSP, nullptr);
}).detach();
setDomeState(DOME_UNPARKING);
ParkSP.setState(IPS_BUSY);
IDSetSwitch(&ParkSP, nullptr);
return IPS_BUSY;
}
virtual IPState ControlShutter(ShutterOperation operation) override
{
if (operation == SHUTTER_OPEN)
{
LOG_INFO("Dome: Opening shutter.");
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(3));
m_isShutterOpen = true;
LOG_INFO("Dome: Shutter opened.");
setShutterState(SHUTTER_OPENED);
DomeShutterSP.setState(IPS_OK);
IDSetSwitch(&DomeShutterSP, nullptr);
}).detach();
setShutterState(SHUTTER_MOVING);
DomeShutterSP.setState(IPS_BUSY);
IDSetSwitch(&DomeShutterSP, nullptr);
return IPS_BUSY;
}
else if (operation == SHUTTER_CLOSE)
{
LOG_INFO("Dome: Closing shutter.");
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(3));
m_isShutterOpen = false;
LOG_INFO("Dome: Shutter closed.");
setShutterState(SHUTTER_CLOSED);
DomeShutterSP.setState(IPS_OK);
IDSetSwitch(&DomeShutterSP, nullptr);
}).detach();
setShutterState(SHUTTER_MOVING);
DomeShutterSP.setState(IPS_BUSY);
IDSetSwitch(&DomeShutterSP, nullptr);
return IPS_BUSY;
}
return IPS_ALERT;
}
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
{
// Forward to base class for Dome properties
if (INDI::Dome::ISNewSwitch(dev, name, states, names, n))
return true;
// Handle any custom switch properties here
return INDI::DefaultDevice::ISNewSwitch(dev, name, states, names, n);
}
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
{
// Forward to base class for Dome properties
if (INDI::Dome::ISNewNumber(dev, name, values, names, n))
return true;
// Handle any custom number properties here
return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
}
virtual void TimerHit() override
{
if (!isConnected())
{
SetTimer(getCurrentPollingPeriod());
return;
}
// Update mount coordinates for slaving
UpdateMountCoords();
UpdateAutoSync(); // Check for auto-sync
// Update dome and shutter states based on internal flags (for simulation)
if (getDomeState() == DOME_MOVING && std::abs(DomeAbsPosNP[0].getValue() - m_currentAzimuth) < 0.1)
{
// If motion is "complete" in simulation, set to idle
setDomeState(DOME_IDLE);
DomeAbsPosNP.setState(IPS_OK);
IDSetNumber(&DomeAbsPosNP, nullptr);
}
SetTimer(getCurrentPollingPeriod());
}
private: double m_currentAzimuth {0.0}; bool m_isShutterOpen {false}; };
// This is typically how an INDI driver is instantiated // static MyDomeDevice myDomeDevice;