Instrument Neutral Distributed Interface INDI  1.5.0
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 
28 {
29  controller = new INDI::Controller(this);
30 
32 }
33 
35 {
36 }
37 
39 {
40  DefaultDevice::initProperties(); // let the base class flesh in what it wants
41 
43 
44  // Presets
45  IUFillNumber(&PresetN[0], "PRESET_1", "Preset 1", "%.f", 0, 100000, 1000, 0);
46  IUFillNumber(&PresetN[1], "PRESET_2", "Preset 2", "%.f", 0, 100000, 1000, 0);
47  IUFillNumber(&PresetN[2], "PRESET_3", "Preset 3", "%.f", 0, 100000, 1000, 0);
48  IUFillNumberVector(&PresetNP, PresetN, 3, getDeviceName(), "Presets", "", "Presets", IP_RW, 0, IPS_IDLE);
49 
50  //Preset GOTO
51  IUFillSwitch(&PresetGotoS[0], "Preset 1", "", ISS_OFF);
52  IUFillSwitch(&PresetGotoS[1], "Preset 2", "", ISS_OFF);
53  IUFillSwitch(&PresetGotoS[2], "Preset 3", "", ISS_OFF);
54  IUFillSwitchVector(&PresetGotoSP, PresetGotoS, 3, getDeviceName(), "Goto", "", "Presets", IP_RW, ISR_1OFMANY, 0,
55  IPS_IDLE);
56 
58 
59  controller->mapController("Focus In", "Focus In", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_1");
60  controller->mapController("Focus Out", "Focus Out", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_2");
61  controller->mapController("Abort Focus", "Abort Focus", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_3");
62 
64 
66 
67  if (focuserConnection & CONNECTION_SERIAL)
68  {
70  serialConnection->registerHandshake([&]() { return callHandshake(); });
72  }
73 
74  if (focuserConnection & CONNECTION_TCP)
75  {
76  tcpConnection = new Connection::TCP(this);
77  tcpConnection->registerHandshake([&]() { return callHandshake(); });
79  }
80 
81  return true;
82 }
83 
84 void INDI::Focuser::ISGetProperties(const char *dev)
85 {
86  // First we let our parent populate
88 
90  return;
91 }
92 
94 {
95  if (isConnected())
96  {
97  // Now we add our focusser specific stuff
99 
100  if (HasVariableSpeed())
101  {
104  }
105  if (CanRelMove())
107  if (CanAbsMove())
109  if (CanAbort())
111  if (CanAbsMove())
112  {
115  }
116  }
117  else
118  {
120  if (HasVariableSpeed())
121  {
124  }
125  if (CanRelMove())
127  if (CanAbsMove())
129  if (CanAbort())
131  if (CanAbsMove())
132  {
135  }
136  }
137 
139  return true;
140 }
141 
142 bool INDI::Focuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
143 {
144  // first check if it's for our device
145  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
146  {
147  if (!strcmp(name, PresetNP.name))
148  {
149  IUUpdateNumber(&PresetNP, values, names, n);
150  PresetNP.s = IPS_OK;
151  IDSetNumber(&PresetNP, nullptr);
152 
153  //saveConfig();
154 
155  return true;
156  }
157 
158  if (strstr(name, "FOCUS_"))
159  return processFocuserNumber(dev, name, values, names, n);
160  }
161 
162  return DefaultDevice::ISNewNumber(dev, name, values, names, n);
163 }
164 
165 bool INDI::Focuser::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
166 {
167  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
168  {
169  if (!strcmp(PresetGotoSP.name, name))
170  {
171  IUUpdateSwitch(&PresetGotoSP, states, names, n);
172  int index = IUFindOnSwitchIndex(&PresetGotoSP);
173 
174  if (PresetN[index].value < FocusAbsPosN[0].min)
175  {
177  IDSetSwitch(&PresetGotoSP, nullptr);
179  "Requested position out of bound. Focus minimum position is %g", FocusAbsPosN[0].min);
180  return false;
181  }
182  else if (PresetN[index].value > FocusAbsPosN[0].max)
183  {
185  IDSetSwitch(&PresetGotoSP, nullptr);
187  "Requested position out of bound. Focus maximum position is %g", FocusAbsPosN[0].max);
188  return false;
189  }
190 
191  int rc = MoveAbsFocuser(PresetN[index].value);
192  if (rc >= 0)
193  {
195  DEBUGF(INDI::Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index + 1,
196  PresetN[index].value);
197  IDSetSwitch(&PresetGotoSP, nullptr);
198  return true;
199  }
200 
202  IDSetSwitch(&PresetGotoSP, nullptr);
203  return false;
204  }
205 
206  if (strstr(name, "FOCUS_"))
207  return processFocuserSwitch(dev, name, states, names, n);
208  }
209 
210  controller->ISNewSwitch(dev, name, states, names, n);
211 
212  // Nobody has claimed this, so, ignore it
213  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
214 }
215 
216 bool INDI::Focuser::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
217 {
218  controller->ISNewText(dev, name, texts, names, n);
219 
220  return DefaultDevice::ISNewText(dev, name, texts, names, n);
221 }
222 
224 {
225  controller->ISSnoopDevice(root);
226 
228 }
229 
231 {
232  return false;
233 }
234 
236 {
238 
240 
242 
243  return true;
244 }
245 
246 void INDI::Focuser::buttonHelper(const char *button_n, ISState state, void *context)
247 {
248  static_cast<INDI::Focuser *>(context)->processButton(button_n, state);
249 }
250 
251 void INDI::Focuser::processButton(const char *button_n, ISState state)
252 {
253  //ignore OFF
254  if (state == ISS_OFF)
255  return;
256 
258 
259  IPState rc = IPS_IDLE;
260 
261  // Abort
262  if (!strcmp(button_n, "Abort Focus"))
263  {
264  if (AbortFocuser())
265  {
266  AbortSP.s = IPS_OK;
267  DEBUG(INDI::Logger::DBG_SESSION, "Focuser aborted.");
268  if (CanAbsMove() && FocusAbsPosNP.s != IPS_IDLE)
269  {
271  IDSetNumber(&FocusAbsPosNP, nullptr);
272  }
273  if (CanRelMove() && FocusRelPosNP.s != IPS_IDLE)
274  {
276  IDSetNumber(&FocusRelPosNP, nullptr);
277  }
278  }
279  else
280  {
281  AbortSP.s = IPS_ALERT;
282  DEBUG(INDI::Logger::DBG_ERROR, "Aborting focuser failed.");
283  }
284 
285  IDSetSwitch(&AbortSP, nullptr);
286  }
287  // Focus In
288  else if (!strcmp(button_n, "Focus In"))
289  {
290  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
291  {
294  IDSetSwitch(&FocusMotionSP, nullptr);
295  }
296 
297  if (HasVariableSpeed())
298  {
299  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
300  FocusTimerNP.s = rc;
301  IDSetNumber(&FocusTimerNP, nullptr);
302  }
303  else if (CanRelMove())
304  {
305  rc = MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
306  if (rc == IPS_OK)
307  {
309  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int)FocusRelPosN[0].value);
310  IDSetNumber(&FocusAbsPosNP, nullptr);
311  }
312  else if (rc == IPS_BUSY)
313  {
315  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int)FocusRelPosN[0].value);
316  }
317  }
318  }
319  else if (!strcmp(button_n, "Focus Out"))
320  {
322  {
325  IDSetSwitch(&FocusMotionSP, nullptr);
326  }
327 
328  if (HasVariableSpeed())
329  {
330  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
331  FocusTimerNP.s = rc;
332  IDSetNumber(&FocusTimerNP, nullptr);
333  }
334  else if (CanRelMove())
335  {
336  rc = MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
337  if (rc == IPS_OK)
338  {
340  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int)FocusRelPosN[0].value);
341  IDSetNumber(&FocusAbsPosNP, nullptr);
342  }
343  else if (rc == IPS_BUSY)
344  {
346  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int)FocusRelPosN[0].value);
347  }
348  }
349  }
350 }
351 
352 bool INDI::Focuser::callHandshake()
353 {
354  if (focuserConnection > 0)
355  {
358  else if (getActiveConnection() == tcpConnection)
360  }
361 
362  return Handshake();
363 }
364 
366 {
367  return focuserConnection;
368 }
369 
370 void INDI::Focuser::setFocuserConnection(const uint8_t &value)
371 {
373 
374  if (value == 0 || (mask & value) == 0)
375  {
376  DEBUGF(INDI::Logger::DBG_ERROR, "Invalid connection mode %d", value);
377  return;
378  }
379 
380  focuserConnection = value;
381 }
int getPortFD() const
Definition: connectiontcp.h:61
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected. ...
Connection::TCP * tcpConnection
Definition: indifocuser.h:99
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver...
Definition: indifocuser.cpp:93
INumberVectorProperty FocusTimerNP
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
Connection::Interface * getActiveConnection()
static void buttonHelper(const char *button_n, ISState state, void *context)
virtual bool initProperties()
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
int getPortFD() const
bool processFocuserSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE. You may send an ORed list of DeviceInterface values.
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file ...
INDI::Controller * controller
Definition: indifocuser.h:96
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:545
virtual void ISGetProperties(const char *dev)
define the driver&#39;s properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
ISState s
Definition: indiapi.h:326
void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...)
Tell client to update an existing switch vector property.
Definition: indidriver.c:1880
IPState
Property state.
Definition: indiapi.h:133
virtual bool updateProperties()
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:227
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
INumberVectorProperty FocusRelPosNP
The Controller class provides functionality to access a controller (e.g. joystick) input and send it ...
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:283
double max(void)
void mapController(const char *propertyName, const char *propertyLabel, ControllerType type, const char *initialValue)
mapController adds a new property to the joystick&#39;s settings.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
void processButton(const char *button_n, ISState state)
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...
Definition: indiapi.h:157
const char * name
Definition: indiserver.c:112
INumberVectorProperty PresetNP
Definition: indifocuser.h:90
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1838
char name[MAXINDINAME]
Definition: indiapi.h:294
void setFocuserConnection(const uint8_t &value)
setFocuserConnection Set Focuser connection mode. Child class should call this in the constructor bef...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
virtual void ISGetProperties(const char *dev)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool Handshake()
perform handshake with device to check communication
void defineSwitch(ISwitchVectorProperty *svp)
Define switch vector to client & register it. Alternatively, IDDefswitch can be used but the property...
INumberVectorProperty FocusAbsPosNP
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidriver.c:1401
virtual void ISGetProperties(const char *dev)
define the driver&#39;s properties to the client. Usually, only a minimum set of properties are defined t...
Definition: indifocuser.cpp:84
INumberVectorProperty FocusSpeedNP
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:384
Connection::Serial * serialConnection
Definition: indifocuser.h:98
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:420
ISwitch PresetGotoS[3]
Definition: indifocuser.h:91
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1296
ISwitchVectorProperty PresetGotoSP
Definition: indifocuser.h:92
Class to provide general functionality of a focuser device.
Definition: indifocuser.h:40
The TCP class manages connection with devices over the network via TCP/IP. Upon successfull connectio...
Definition: connectiontcp.h:37
char name[MAXINDINAME]
Definition: indiapi.h:342
virtual ~Focuser()
Definition: indifocuser.cpp:34
virtual IPState MoveAbsFocuser(uint32_t targetTicks)
MoveFocuser the focuser to an absolute position.
virtual bool saveConfigItems(FILE *fp)
bool processFocuserNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
uint8_t getFocuserConnection() const
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
const char * getDeviceName()
virtual bool ISSnoopDevice(XMLEle *root)
ISwitchVectorProperty AbortSP
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function...
ISState
Switch state.
Definition: indiapi.h:124
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:494
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual bool AbortFocuser()
AbortFocuser all focus motion.
double min(void)
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
#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:60
ISwitchVectorProperty FocusMotionSP
void initFocuserProperties(const char *deviceName, const char *groupName)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function...
Definition: indifocuser.cpp:38
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void defineNumber(INumberVectorProperty *nvp)
Define number vector to client & register it. Alternatively, IDDefNumber can be used but the property...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
INumber PresetN[3]
Definition: indifocuser.h:89
double value
Definition: indiapi.h:261