Instrument Neutral Distributed Interface INDI  1.2.0
indifocuser.cpp
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 <string.h>
22 
23 INDI::Focuser::Focuser()
24 {
25  controller = new INDI::Controller(this);
26 
27  controller->setButtonCallback(buttonHelper);
28 }
29 
30 INDI::Focuser::~Focuser()
31 {
32 }
33 
35 {
36  DefaultDevice::initProperties(); // let the base class flesh in what it wants
37 
38  initFocuserProperties(getDeviceName(), MAIN_CONTROL_TAB);
39 
40  /* Port */
41  IUFillText(&PortT[0], "PORT", "Port", "/dev/ttyUSB0");
42  IUFillTextVector(&PortTP, PortT, 1, getDeviceName(), "DEVICE_PORT", "Ports", OPTIONS_TAB, IP_RW, 0, IPS_IDLE);
43 
44  // Presets
45  IUFillNumber(&PresetN[0], "Preset 1", "", "%6.2f", 0, 60000, 1000, 0);
46  IUFillNumber(&PresetN[1], "Preset 2", "", "%6.2f", 0, 60000, 1000, 0);
47  IUFillNumber(&PresetN[2], "Preset 3", "", "%6.2f", 0, 60000, 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, IPS_IDLE);
55 
57 
58  controller->mapController("Focus In", "Focus In", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_1");
59  controller->mapController("Focus Out", "Focus Out", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_2");
60  controller->mapController("Abort Focus", "Abort Focus", INDI::Controller::CONTROLLER_BUTTON, "BUTTON_3");
61 
62  controller->initProperties();
63 
65 
66  return true;
67 }
68 
69 void INDI::Focuser::ISGetProperties (const char *dev)
70 {
71  // First we let our parent populate
73 
74  defineText(&PortTP);
75  loadConfig(true, "DEVICE_PORT");
76 
77  controller->ISGetProperties(dev);
78  return;
79 }
80 
82 {
83  if(isConnected())
84  {
85  // Now we add our focusser specific stuff
86  defineSwitch(&FocusMotionSP);
87 
88  if (HasVariableSpeed())
89  {
90  defineNumber(&FocusSpeedNP);
91  defineNumber(&FocusTimerNP);
92  }
93  if (CanRelMove())
94  defineNumber(&FocusRelPosNP);
95  if (CanAbsMove())
96  defineNumber(&FocusAbsPosNP);
97  if (CanAbort())
98  defineSwitch(&AbortSP);
99  if (CanAbsMove())
100  {
101  defineNumber(&PresetNP);
102  defineSwitch(&PresetGotoSP);
103  }
104  } else
105  {
106  deleteProperty(FocusMotionSP.name);
107  if (HasVariableSpeed())
108  {
109  deleteProperty(FocusSpeedNP.name);
110  deleteProperty(FocusTimerNP.name);
111  }
112  if (CanRelMove())
113  deleteProperty(FocusRelPosNP.name);
114  if (CanAbsMove())
115  deleteProperty(FocusAbsPosNP.name);
116  if (CanAbort())
117  deleteProperty(AbortSP.name);
118  if (CanAbsMove())
119  {
120  deleteProperty(PresetNP.name);
121  deleteProperty(PresetGotoSP.name);
122  }
123  }
124 
125  controller->updateProperties();
126  return true;
127 }
128 
129 
130 bool INDI::Focuser::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
131 {
132  // first check if it's for our device
133  if(strcmp(dev,getDeviceName())==0)
134  {
135  if (!strcmp(name, PresetNP.name))
136  {
137  IUUpdateNumber(&PresetNP, values, names, n);
138  PresetNP.s = IPS_OK;
139  IDSetNumber(&PresetNP, NULL);
140 
141  //saveConfig();
142 
143  return true;
144  }
145 
146  if (strstr(name, "FOCUS_"))
147  return processFocuserNumber(dev, name, values, names, n);
148 
149  }
150 
151  return DefaultDevice::ISNewNumber(dev,name,values,names,n);
152 }
153 
154 bool INDI::Focuser::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
155 {
156  if(strcmp(dev,getDeviceName())==0)
157  {
158  if (!strcmp(PresetGotoSP.name, name))
159  {
160  IUUpdateSwitch(&PresetGotoSP, states, names, n);
161  int index = IUFindOnSwitchIndex(&PresetGotoSP);
162 
163  if (PresetN[index].value < FocusAbsPosN[0].min)
164  {
165  PresetGotoSP.s = IPS_ALERT;
166  IDSetSwitch(&PresetGotoSP, NULL);
167  DEBUGFDEVICE(dev, INDI::Logger::DBG_ERROR, "Requested position out of bound. Focus minimum position is %g", FocusAbsPosN[0].min);
168  return false;
169  }
170  else if (PresetN[index].value > FocusAbsPosN[0].max)
171  {
172  PresetGotoSP.s = IPS_ALERT;
173  IDSetSwitch(&PresetGotoSP, NULL);
174  DEBUGFDEVICE(dev, INDI::Logger::DBG_ERROR, "Requested position out of bound. Focus maximum position is %g", FocusAbsPosN[0].max);
175  return false;
176  }
177 
178  int rc = MoveAbsFocuser(PresetN[index].value);
179  if (rc >= 0)
180  {
181  PresetGotoSP.s = IPS_OK;
182  DEBUGF(INDI::Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index+1, PresetN[index].value);
183  IDSetSwitch(&PresetGotoSP, NULL);
184  return true;
185  }
186 
187  PresetGotoSP.s = IPS_ALERT;
188  IDSetSwitch(&PresetGotoSP, NULL);
189  return false;
190  }
191 
192  if (strstr(name, "FOCUS_"))
193  return processFocuserSwitch(dev, name, states, names, n);
194 
195  }
196 
197  controller->ISNewSwitch(dev, name, states, names, n);
198 
199  // Nobody has claimed this, so, ignore it
200  return DefaultDevice::ISNewSwitch(dev,name,states,names,n);
201 }
202 
203 bool INDI::Focuser::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
204 {
205  if(strcmp(dev,getDeviceName())==0)
206  {
207  if (!strcmp(name, PortTP.name))
208  {
209  IUUpdateText(&PortTP, texts, names, n);
210  PortTP.s = IPS_OK;
211  IDSetText(&PortTP, NULL);
212  return true;
213  }
214  }
215 
216  controller->ISNewText(dev, name, texts, names, n);
217 
218  return DefaultDevice::ISNewText(dev, name, texts, names, n);
219 }
220 
221 bool INDI::Focuser::ISSnoopDevice (XMLEle *root)
222 {
223  controller->ISSnoopDevice(root);
224 
226 }
227 
229 {
230  IUSaveConfigText(fp, &PortTP);
231  IUSaveConfigNumber(fp, &PresetNP);
232 
233  controller->saveConfigItems(fp);
234 
235  return true;
236 }
237 
238 void INDI::Focuser::buttonHelper(const char *button_n, ISState state, void *context)
239 {
240  static_cast<INDI::Focuser *>(context)->processButton(button_n, state);
241 }
242 
243 void INDI::Focuser::processButton(const char * button_n, ISState state)
244 {
245  //ignore OFF
246  if (state == ISS_OFF)
247  return;
248 
249  FocusTimerN[0].value = lastTimerValue;
250 
251  IPState rc= IPS_IDLE;
252 
253  // Abort
254  if (!strcmp(button_n, "Abort Focus"))
255  {
256  if (AbortFocuser())
257  {
258  AbortSP.s = IPS_OK;
259  DEBUG(INDI::Logger::DBG_SESSION, "Focuser aborted.");
260  if (CanAbsMove() && FocusAbsPosNP.s != IPS_IDLE)
261  {
262  FocusAbsPosNP.s = IPS_IDLE;
263  IDSetNumber(&FocusAbsPosNP, NULL);
264  }
265  if (CanRelMove() && FocusRelPosNP.s != IPS_IDLE)
266  {
267  FocusRelPosNP.s = IPS_IDLE;
268  IDSetNumber(&FocusRelPosNP, NULL);
269  }
270  }
271  else
272  {
273  AbortSP.s = IPS_ALERT;
274  DEBUG(INDI::Logger::DBG_ERROR, "Aborting focuser failed.");
275  }
276 
277  IDSetSwitch(&AbortSP, NULL);
278  }
279  // Focus In
280  else if (!strcmp(button_n, "Focus In"))
281  {
282  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
283  {
284  FocusMotionS[FOCUS_INWARD].s = ISS_ON;
285  FocusMotionS[FOCUS_OUTWARD].s = ISS_OFF;
286  IDSetSwitch(&FocusMotionSP, NULL);
287  }
288 
289  if (HasVariableSpeed())
290  {
291  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
292  FocusTimerNP.s = rc;
293  IDSetNumber(&FocusTimerNP,NULL);
294  }
295  else if (CanRelMove())
296  {
297  rc=MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
298  if (rc == IPS_OK)
299  {
300  FocusRelPosNP.s=IPS_OK;
301  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int) FocusRelPosN[0].value);
302  IDSetNumber(&FocusAbsPosNP, NULL);
303  }
304  else if (rc == IPS_BUSY)
305  {
306  FocusRelPosNP.s=IPS_BUSY;
307  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int) FocusRelPosN[0].value);
308  }
309  }
310  }
311  else if (!strcmp(button_n, "Focus Out"))
312  {
313  if (FocusMotionS[FOCUS_OUTWARD].s != ISS_ON)
314  {
315  FocusMotionS[FOCUS_INWARD].s = ISS_OFF;
316  FocusMotionS[FOCUS_OUTWARD].s = ISS_ON;
317  IDSetSwitch(&FocusMotionSP, NULL);
318  }
319 
320  if (HasVariableSpeed())
321  {
322  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
323  FocusTimerNP.s = rc;
324  IDSetNumber(&FocusTimerNP,NULL);
325  }
326  else if (CanRelMove())
327  {
328  rc=MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
329  if (rc == IPS_OK)
330  {
331  FocusRelPosNP.s=IPS_OK;
332  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int) FocusRelPosN[0].value);
333  IDSetNumber(&FocusAbsPosNP, NULL);
334  }
335  else if (rc == IPS_BUSY)
336  {
337  FocusRelPosNP.s=IPS_BUSY;
338  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int) FocusRelPosN[0].value);
339  }
340  }
341  }
342 }
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indidriver.c:1359
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected. ...
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver...
Definition: indifocuser.cpp:81
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
virtual IPState MoveAbsFocuser(uint32_t ticks)
MoveFocuser the focuser to an absolute position.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
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 ...
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:515
virtual void ISGetProperties(const char *dev)
define the driver&#39;s properties to the client. Usually, only a minumum set of properties are defined t...
ISState s
Definition: indiapi.h:297
void IDSetText(const ITextVectorProperty *t, const char *msg,...)
Tell client to update an existing text vector property.
Definition: indidriver.c:1712
void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...)
Tell client to update an existing switch vector property.
Definition: indidriver.c:1792
IPState
Property state.
Definition: indiapi.h:129
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:221
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:312
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:275
void mapController(const char *propertyName, const char *propertyLabel, ControllerType type, const char *initialValue)
mapController adds a new property to the joystick&#39;s settings.
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:154
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1752
char name[MAXINDINAME]
Definition: indiapi.h:270
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:431
void defineSwitch(ISwitchVectorProperty *svp)
Define switch vector to client & register it. Alternatively, IDDefswitch can be used but the property...
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidriver.c:1340
virtual void ISGetProperties(const char *dev)
define the driver&#39;s properties to the client. Usually, only a minumum set of properties are defined t...
Definition: indifocuser.cpp:69
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:379
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:410
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1201
virtual bool loadConfig(bool silent=false, const char *property=NULL)
Load the last saved configuration file.
Class to provide general functionality of a focuser device.
Definition: indifocuser.h:37
char name[MAXINDINAME]
Definition: indiapi.h:309
bool processFocuserNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
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 ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
char name[MAXINDINAME]
Definition: indiapi.h:214
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...
void defineText(ITextVectorProperty *tvp)
Define text vector to client & register it. Alternatively, IDDefText can be used but the property wil...
ISState
Switch state.
Definition: indiapi.h:120
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:472
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:538
virtual bool AbortFocuser()
AbortFocuser all focus motion.
void addDebugControl()
Add Debug control to the driver.
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:34
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.
double value
Definition: indiapi.h:244