Instrument Neutral Distributed Interface INDI 2.2.5
indifocuser.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2013 Jasem Mutlaq. All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*******************************************************************************/
18
19#include "indifocuser.h"
20
21#include "indicontroller.h"
24
25#include <cstring>
26
27namespace INDI
28{
29
36
38{
39 delete (controller);
40}
41
43{
44 DefaultDevice::initProperties(); // let the base class flesh in what it wants
45
47
48 // Presets
49 PresetNP[0].fill("PRESET_1", "Preset 1", "%.f", 0, 100000, 1000, 0);
50 PresetNP[1].fill("PRESET_2", "Preset 2", "%.f", 0, 100000, 1000, 0);
51 PresetNP[2].fill("PRESET_3", "Preset 3", "%.f", 0, 100000, 1000, 0);
52 PresetNP.fill(getDeviceName(), "Presets", "", "Presets", IP_RW, 0, IPS_IDLE);
53
54 //Preset GOTO
55 PresetGotoSP[0].fill("Preset 1", "", ISS_OFF);
56 PresetGotoSP[1].fill("Preset 2", "", ISS_OFF);
57 PresetGotoSP[2].fill("Preset 3", "", ISS_OFF);
58 PresetGotoSP.fill(getDeviceName(), "Goto", "", "Presets", IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
59
62
63 controller->mapController("Focus In", "Focus In", Controller::CONTROLLER_BUTTON, "BUTTON_1");
64 controller->mapController("Focus Out", "Focus Out", Controller::CONTROLLER_BUTTON, "BUTTON_2");
65 controller->mapController("Abort Focus", "Abort Focus", Controller::CONTROLLER_BUTTON, "BUTTON_3");
66
68
70
71 if (focuserConnection & CONNECTION_SERIAL)
72 {
75 {
76 return callHandshake();
77 });
79 }
80
81 if (focuserConnection & CONNECTION_TCP)
82 {
85 {
86 return callHandshake();
87 });
89 }
90
91 return true;
92}
93
94void Focuser::ISGetProperties(const char *dev)
95{
96 // First we let our parent populate
98
100 return;
101}
102
104{
106
107 if (isConnected())
108 {
109 if (CanAbsMove())
110 {
113 }
114 }
115 else
116 {
117 if (CanAbsMove())
118 {
121 }
122 }
123
125 return true;
126}
127
128bool Focuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
129{
130 if (FI::processNumber(dev, name, values, names, n))
131 return true;
132
133 // first check if it's for our device
134 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
135 {
136 if (PresetNP.isNameMatch(name))
137 {
138 PresetNP.update(values, names, n);
140 PresetNP.apply();
141
143 return true;
144 }
145 }
146
147 return DefaultDevice::ISNewNumber(dev, name, values, names, n);
148}
149
150bool Focuser::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
151{
152 if (FI::processSwitch(dev, name, states, names, n))
153 return true;
154
155 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
156 {
157 if (PresetGotoSP.isNameMatch(name))
158 {
159 PresetGotoSP.update(states, names, n);
160 int index = PresetGotoSP.findOnSwitchIndex();
161
162 if (PresetNP[index].getValue() < FocusAbsPosNP[0].getMin())
163 {
167 "Requested position out of bound. Focus minimum position is %g", FocusAbsPosNP[0].getMin());
168 return true;
169 }
170 else if (PresetNP[index].getValue() > FocusAbsPosNP[0].getMax())
171 {
175 "Requested position out of bound. Focus maximum position is %g", FocusAbsPosNP[0].getMax());
176 return true;
177 }
178
179 IPState rc = MoveAbsFocuser(PresetNP[index].getValue());
180 if (rc != IPS_ALERT)
181 {
183 DEBUGF(Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index + 1,
184 PresetNP[index].getValue());
186
189 return true;
190 }
191
194 return true;
195 }
196 }
197
198 controller->ISNewSwitch(dev, name, states, names, n);
199 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
200}
201
202bool Focuser::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
203{
204 controller->ISNewText(dev, name, texts, names, n);
205
206 return DefaultDevice::ISNewText(dev, name, texts, names, n);
207}
208
210{
212
213 return DefaultDevice::ISSnoopDevice(root);
214}
215
217{
218 return false;
219}
220
222{
224
226
227 PresetNP.save(fp);
229
230 return true;
231}
232
233void Focuser::buttonHelper(const char *button_n, ISState state, void *context)
234{
235 static_cast<Focuser *>(context)->processButton(button_n, state);
236}
237
238void Focuser::processButton(const char *button_n, ISState state)
239{
240 //ignore OFF
241 if (state == ISS_OFF)
242 return;
243
244 FocusTimerNP[0].setValue(lastTimerValue);
245
246 IPState rc = IPS_IDLE;
247
248 // Abort
249 if (!strcmp(button_n, "Abort Focus"))
250 {
251 if (AbortFocuser())
252 {
254 DEBUG(Logger::DBG_SESSION, "Focuser aborted.");
256 {
259 }
261 {
264 }
265 }
266 else
267 {
269 DEBUG(Logger::DBG_ERROR, "Aborting focuser failed.");
270 }
271
273 }
274 // Focus In
275 else if (!strcmp(button_n, "Focus In"))
276 {
277 if (FocusMotionSP[FOCUS_INWARD].getState() != ISS_ON)
278 {
282 }
283
284 if (CanRelMove())
285 {
286 rc = MoveRelFocuser(FOCUS_INWARD, FocusRelPosNP[0].getValue());
287 if (rc == IPS_OK)
288 {
290 FocusRelPosNP.apply("Focuser moved %d steps inward", (int)FocusRelPosNP[0].getValue());
292 }
293 else if (rc == IPS_BUSY)
294 {
296 FocusAbsPosNP.apply("Focuser is moving %d steps inward...", (int)FocusRelPosNP[0].getValue());
297 }
298 }
299 else if (HasVariableSpeed())
300 {
301 rc = MoveFocuser(FOCUS_INWARD, FocusSpeedNP[0].getValue(), FocusTimerNP[0].getValue());
304 }
305
306 }
307 else if (!strcmp(button_n, "Focus Out"))
308 {
309 if (FocusMotionSP[FOCUS_OUTWARD].getState() != ISS_ON)
310 {
314 }
315
316 if (CanRelMove())
317 {
318 rc = MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosNP[0].getValue());
319 if (rc == IPS_OK)
320 {
322 FocusRelPosNP.apply("Focuser moved %d steps outward", (int)FocusRelPosNP[0].getValue());
324 }
325 else if (rc == IPS_BUSY)
326 {
328 FocusAbsPosNP.apply("Focuser is moving %d steps outward...", (int)FocusRelPosNP[0].getValue());
329 }
330 }
331 else if (HasVariableSpeed())
332 {
333 rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedNP[0].getValue(), FocusTimerNP[0].getValue());
336 }
337 }
338}
339
340bool Focuser::callHandshake()
341{
342 if (focuserConnection > 0)
343 {
348 }
349
350 return Handshake();
351}
352
353void Focuser::setSupportedConnections(const uint8_t &value)
354{
356
357 if (value == 0 || (mask & value) == 0)
358 {
359 DEBUGF(Logger::DBG_ERROR, "Invalid connection mode %d", value);
360 return;
361 }
362
363 focuserConnection = value;
364}
365
367{
368 SyncPresets(ticks);
369 return true;
370}
371
372void Focuser::SyncPresets(uint32_t ticks)
373{
374 PresetNP[0].setMax(ticks);
375 PresetNP[0].setStep(PresetNP[0].getMax() / 50.0);
376 PresetNP[1].setMax(ticks);
377 PresetNP[1].setStep(PresetNP[0].getMax() / 50.0);
378 PresetNP[2].setMax(ticks);
379 PresetNP[2].setStep(PresetNP[0].getMax() / 50.0);
381}
382}
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
The TCP class manages connection with devices over the network via TCP/IP. Upon successful connection...
int getPortFD() const
bool isConnected() const
const char * getDeviceName() const
The Controller class provides functionality to access a controller (e.g. joystick) input and send it ...
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected.
virtual bool ISSnoopDevice(XMLEle *root)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
void mapController(const char *propertyName, const char *propertyLabel, ControllerType type, const char *initialValue)
mapController adds a new property to the joystick's settings.
virtual bool initProperties()
virtual bool saveConfigItems(FILE *fp)
virtual void ISGetProperties(const char *dev)
virtual bool updateProperties()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
void addPollPeriodControl()
Add Polling period control to the driver.
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Connection::Interface * getActiveConnection()
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
Provides interface to implement focuser functionality.
INDI::PropertyNumber FocusRelPosNP
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
MoveFocuser the focuser in a particular direction with a specific speed for a finite duration.
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
INDI::PropertySwitch FocusMotionSP
INDI::PropertyNumber FocusSpeedNP
INDI::PropertySwitch FocusAbortSP
INDI::PropertyNumber FocusTimerNP
void initProperties(const char *groupName)
Initialize focuser properties. It is recommended to call this function within initProperties() of you...
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
virtual bool AbortFocuser()
AbortFocuser all focus motion.
INDI::PropertyNumber FocusAbsPosNP
virtual IPState MoveAbsFocuser(uint32_t targetTicks)
MoveFocuser the focuser to an absolute position.
virtual bool ISSnoopDevice(XMLEle *root) override
Processes properties snooped from other devices. Delegates processing to the controller and the base ...
void processButton(const char *button_n, ISState state)
Processes button press events received from the controller via buttonHelper. Handles actions like "Fo...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
Focuser()
Construct a new Focuser object. Initializes the controller and sets up the FocuserInterface.
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
Connection::TCP * tcpConnection
virtual ~Focuser()
Destroy the Focuser object. Cleans up the controller resource.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
INDI::PropertySwitch PresetGotoSP
virtual void SyncPresets(uint32_t ticks)
Synchronizes the range (min, max, step) of the preset number properties (PresetNP) based on the focus...
Connection::Serial * serialConnection
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Processes incoming new text values from the client for this device. Delegates processing to the contr...
Controller * controller
static void buttonHelper(const char *button_n, ISState state, void *context)
Static callback function used by the Controller class. Forwards button press events to the appropriat...
INDI::PropertyNumber PresetNP
void setSupportedConnections(const uint8_t &value)
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
virtual bool Handshake()
Performs a device-specific handshake after a connection is established. This method should be overrid...
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
Definition indilogger.h:56
#define DEBUGFDEVICE(device, priority, msg,...)
Definition indilogger.h:61
#define DEBUGF(priority, msg,...)
Definition indilogger.h:57
Namespace to encapsulate INDI client, drivers, and mediator classes.