File: dome.cpp

package info (click to toggle)
indi 1.9.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 13,668 kB
  • sloc: cpp: 186,148; ansic: 30,833; xml: 869; sh: 282; makefile: 11
file content (176 lines) | stat: -rw-r--r-- 6,614 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
   INDI Developers Manual
   Tutorial #5 - Snooping

   Dome

   Refer to README, which contains instruction on how to build this driver, and use it
   with an INDI-compatible client.

*/

/** \file dome.cpp
    \brief Construct a dome device that the user may operate to open or close the dome shutter door. This driver is \e snooping on the Rain Detector rain property status.
    If rain property state is alert, we close the dome shutter door if it is open, and we prevent the user from opening it until the rain threat passes.
    \author Jasem Mutlaq

    \example dome.cpp
    The dome driver \e snoops on the rain detector signal and watches whether rain is detected or not. If it is detector and the dome is closed, it performs
    no action, but it also prevents you from opening the dome due to rain. If the dome is open, it will automatically starts closing the shutter. In order
    snooping to work, both drivers must be started by the same indiserver (or chained INDI servers):
    \code indiserver tutorial_dome tutorial_rain \endcode
    The dome driver keeps a copy of RainL light property from the rain driver. This makes it easy to parse the property status once an update from the rain
    driver arrives in the dome driver. Alternatively, you can directly parse the XML root element in ISSnoopDevice(XMLEle *root) to extract the required data.
*/

#include "dome.h"
#include <inditimer.h>

#include <memory>
#include <cstring>
#include <unistd.h>

std::unique_ptr<Dome> dome(new Dome());

/**************************************************************************************
** Client is asking us to establish connection to the device
***************************************************************************************/
bool Dome::Connect()
{
    IDMessage(getDeviceName(), "Dome connected successfully!");
    return true;
}

/**************************************************************************************
** Client is asking us to terminate connection to the device
***************************************************************************************/
bool Dome::Disconnect()
{
    IDMessage(getDeviceName(), "Dome disconnected successfully!");
    return true;
}

/**************************************************************************************
** INDI is asking us for our default device name
***************************************************************************************/
const char *Dome::getDefaultName()
{
    return "Dome";
}

/**************************************************************************************
** INDI is asking us to init our properties.
***************************************************************************************/
bool Dome::initProperties()
{
    // Must init parent properties first!
    INDI::DefaultDevice::initProperties();

    mShutterSwitch[0].fill("Open", "", ISS_ON);
    mShutterSwitch[1].fill("Close", "", ISS_OFF);
    mShutterSwitch.fill(getDeviceName(), "Shutter Door", "", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
    mShutterSwitch.onUpdate([this]()
    {
        if (mShutterSwitch[0].getState() == ISS_ON)
            openShutter();
        else
            closeShutter();

    });
    // We init here the property we wish to "snoop" from the target device
    mRainLight[0].fill("Status", "", IPS_IDLE);

    // wait for "Rain Detector" driver
    watchDevice("Rain Detector", [this](INDI::BaseDevice device)
    {
        // wait for "Rain Alert" property available
        device.watchProperty("Rain Alert", [this](INDI::PropertyLight rain)
        {
            mRainLight = rain; // we have real rainLight property, override mRainLight
            static IPState oldRainState = rain[0].getState();

            rain.onUpdate([this, rain]()
            {
                IPState newRainState = rain[0].getState();
                if (newRainState == IPS_ALERT)
                {
                    // If dome is open, then close it */
                    if (mShutterSwitch[0].getState() == ISS_ON)
                        closeShutter();
                    else
                        IDMessage(getDeviceName(), "Rain Alert Detected! Dome is already closed.");
                }
                
                if (newRainState != IPS_ALERT && oldRainState == IPS_ALERT)
                {
                    IDMessage(getDeviceName(), "Rain threat passed. Opening the dome is now safe.");
                }

                oldRainState = newRainState;
            });
        });
    });

    return true;
}

/********************************************************************************************
** INDI is asking us to update the properties because there is a change in CONNECTION status
** This fucntion is called whenever the device is connected or disconnected.
*********************************************************************************************/
bool Dome::updateProperties()
{
    // Call parent update properties first
    INDI::DefaultDevice::updateProperties();

    if (isConnected())
        defineProperty(mShutterSwitch);
    else
        // We're disconnected
        deleteProperty(mShutterSwitch);

    return true;
}

/********************************************************************************************
** Close shutter
*********************************************************************************************/
void Dome::closeShutter()
{
    mShutterSwitch.setState(IPS_BUSY);
    mShutterSwitch.apply("Shutter is closing...");

    INDI::Timer::singleShot(5000 /* ms */, [this](){
        mShutterSwitch[0].setState(ISS_OFF);
        mShutterSwitch[1].setState(ISS_ON);

        mShutterSwitch.setState(IPS_OK);
        mShutterSwitch.apply("Shutter is closed.");
    });
}

/********************************************************************************************
** Open shutter
*********************************************************************************************/
void Dome::openShutter()
{
    if (mRainLight[0].getState() == IPS_ALERT)
    {
        mShutterSwitch.setState(IPS_ALERT);
        mShutterSwitch[0].setState(ISS_OFF);
        mShutterSwitch[1].setState(ISS_ON);
        mShutterSwitch.apply("It is raining, cannot open Shutter.");
        return;
    }

    mShutterSwitch.setState(IPS_BUSY);
    mShutterSwitch.apply("Shutter is opening...");

    INDI::Timer::singleShot(5000 /* ms */, [this](){
        mShutterSwitch[0].setState(ISS_ON);
        mShutterSwitch[1].setState(ISS_OFF);

        mShutterSwitch.setState(IPS_OK);
        mShutterSwitch.apply("Shutter is open.");
    });
}