Instrument Neutral Distributed Interface INDI  1.4.1
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 {
231 
232  IUSaveConfigText(fp, &PortTP);
233  IUSaveConfigNumber(fp, &PresetNP);
234 
235  controller->saveConfigItems(fp);
236 
237  return true;
238 }
239 
240 void INDI::Focuser::buttonHelper(const char *button_n, ISState state, void *context)
241 {
242  static_cast<INDI::Focuser *>(context)->processButton(button_n, state);
243 }
244 
245 void INDI::Focuser::processButton(const char * button_n, ISState state)
246 {
247  //ignore OFF
248  if (state == ISS_OFF)
249  return;
250 
251  FocusTimerN[0].value = lastTimerValue;
252 
253  IPState rc= IPS_IDLE;
254 
255  // Abort
256  if (!strcmp(button_n, "Abort Focus"))
257  {
258  if (AbortFocuser())
259  {
260  AbortSP.s = IPS_OK;
261  DEBUG(INDI::Logger::DBG_SESSION, "Focuser aborted.");
262  if (CanAbsMove() && FocusAbsPosNP.s != IPS_IDLE)
263  {
264  FocusAbsPosNP.s = IPS_IDLE;
265  IDSetNumber(&FocusAbsPosNP, NULL);
266  }
267  if (CanRelMove() && FocusRelPosNP.s != IPS_IDLE)
268  {
269  FocusRelPosNP.s = IPS_IDLE;
270  IDSetNumber(&FocusRelPosNP, NULL);
271  }
272  }
273  else
274  {
275  AbortSP.s = IPS_ALERT;
276  DEBUG(INDI::Logger::DBG_ERROR, "Aborting focuser failed.");
277  }
278 
279  IDSetSwitch(&AbortSP, NULL);
280  }
281  // Focus In
282  else if (!strcmp(button_n, "Focus In"))
283  {
284  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
285  {
286  FocusMotionS[FOCUS_INWARD].s = ISS_ON;
287  FocusMotionS[FOCUS_OUTWARD].s = ISS_OFF;
288  IDSetSwitch(&FocusMotionSP, NULL);
289  }
290 
291  if (HasVariableSpeed())
292  {
293  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
294  FocusTimerNP.s = rc;
295  IDSetNumber(&FocusTimerNP,NULL);
296  }
297  else if (CanRelMove())
298  {
299  rc=MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
300  if (rc == IPS_OK)
301  {
302  FocusRelPosNP.s=IPS_OK;
303  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int) FocusRelPosN[0].value);
304  IDSetNumber(&FocusAbsPosNP, NULL);
305  }
306  else if (rc == IPS_BUSY)
307  {
308  FocusRelPosNP.s=IPS_BUSY;
309  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int) FocusRelPosN[0].value);
310  }
311  }
312  }
313  else if (!strcmp(button_n, "Focus Out"))
314  {
315  if (FocusMotionS[FOCUS_OUTWARD].s != ISS_ON)
316  {
317  FocusMotionS[FOCUS_INWARD].s = ISS_OFF;
318  FocusMotionS[FOCUS_OUTWARD].s = ISS_ON;
319  IDSetSwitch(&FocusMotionSP, NULL);
320  }
321 
322  if (HasVariableSpeed())
323  {
324  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
325  FocusTimerNP.s = rc;
326  IDSetNumber(&FocusTimerNP,NULL);
327  }
328  else if (CanRelMove())
329  {
330  rc=MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
331  if (rc == IPS_OK)
332  {
333  FocusRelPosNP.s=IPS_OK;
334  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int) FocusRelPosN[0].value);
335  IDSetNumber(&FocusAbsPosNP, NULL);
336  }
337  else if (rc == IPS_BUSY)
338  {
339  FocusRelPosNP.s=IPS_BUSY;
340  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int) FocusRelPosN[0].value);
341  }
342  }
343  }
344 }
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indidriver.c:1422
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:542
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...
ISState s
Definition: indiapi.h:296
void IDSetText(const ITextVectorProperty *t, const char *msg,...)
Tell client to update an existing text vector property.
Definition: indidriver.c:1792
void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...)
Tell client to update an existing switch vector property.
Definition: indidriver.c:1872
IPState
Property state.
Definition: indiapi.h:128
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:222
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:313
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:276
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:153
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1832
char name[MAXINDINAME]
Definition: indiapi.h:269
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
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:441
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:1403
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: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:380
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:417
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1244
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:308
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:213
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:119
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:491
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:569
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:243