Instrument Neutral Distributed Interface INDI  1.0.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", MAIN_CONTROL_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 
56  addDebugControl();
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 
61  controller->initProperties();
62 
63  setInterfaceDescriptor(FOCUSER_INTERFACE);
64 
65  return true;
66 }
67 
68 void INDI::Focuser::ISGetProperties (const char *dev)
69 {
70  // First we let our parent populate
72 
73  defineText(&PortTP);
74 
75  controller->ISGetProperties(dev);
76  return;
77 }
78 
80 {
81  if(isConnected())
82  {
83  // Now we add our focusser specific stuff
84  defineSwitch(&FocusMotionSP);
85 
86  if (capability.variableSpeed)
87  {
88  defineNumber(&FocusSpeedNP);
89  defineNumber(&FocusTimerNP);
90  }
91  if (capability.canRelMove)
92  defineNumber(&FocusRelPosNP);
93  if (capability.canAbsMove)
94  defineNumber(&FocusAbsPosNP);
95  if (capability.canAbort)
96  defineSwitch(&AbortSP);
97  if (capability.canAbsMove)
98  {
99  defineNumber(&PresetNP);
100  defineSwitch(&PresetGotoSP);
101  }
102  } else
103  {
104  deleteProperty(FocusMotionSP.name);
105  if (capability.variableSpeed)
106  {
107  deleteProperty(FocusSpeedNP.name);
108  deleteProperty(FocusTimerNP.name);
109  }
110  if (capability.canRelMove)
111  deleteProperty(FocusRelPosNP.name);
112  if (capability.canAbsMove)
113  deleteProperty(FocusAbsPosNP.name);
114  if (capability.canAbort)
115  deleteProperty(AbortSP.name);
116  if (capability.canAbsMove)
117  {
118  deleteProperty(PresetNP.name);
119  deleteProperty(PresetGotoSP.name);
120  }
121  }
122 
123  controller->updateProperties();
124  return true;
125 }
126 
127 
128 bool INDI::Focuser::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
129 {
130  // first check if it's for our device
131  if(strcmp(dev,getDeviceName())==0)
132  {
133  if (!strcmp(name, PresetNP.name))
134  {
135  IUUpdateNumber(&PresetNP, values, names, n);
136  PresetNP.s = IPS_OK;
137  IDSetNumber(&PresetNP, NULL);
138 
139  //saveConfig();
140 
141  return true;
142  }
143 
144  if (strstr(name, "FOCUS_"))
145  return processFocuserNumber(dev, name, values, names, n);
146 
147  }
148 
149  return DefaultDevice::ISNewNumber(dev,name,values,names,n);
150 }
151 
152 bool INDI::Focuser::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
153 {
154  if(strcmp(dev,getDeviceName())==0)
155  {
156  if (!strcmp(PresetGotoSP.name, name))
157  {
158  IUUpdateSwitch(&PresetGotoSP, states, names, n);
159  int index = IUFindOnSwitchIndex(&PresetGotoSP);
160  int rc = MoveAbsFocuser(PresetN[index].value);
161  if (rc >= 0)
162  {
163  PresetGotoSP.s = IPS_OK;
164  DEBUGF(INDI::Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index+1, PresetN[index].value);
165  IDSetSwitch(&PresetGotoSP, NULL);
166  return true;
167  }
168 
169  PresetGotoSP.s = IPS_ALERT;
170  IDSetSwitch(&PresetGotoSP, NULL);
171  return false;
172  }
173 
174  if (strstr(name, "FOCUS_"))
175  return processFocuserSwitch(dev, name, states, names, n);
176 
177  }
178 
179  controller->ISNewSwitch(dev, name, states, names, n);
180 
181  // Nobody has claimed this, so, ignore it
182  return DefaultDevice::ISNewSwitch(dev,name,states,names,n);
183 }
184 
185 bool INDI::Focuser::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
186 {
187  if(strcmp(dev,getDeviceName())==0)
188  {
189  if (!strcmp(name, PortTP.name))
190  {
191  IUUpdateText(&PortTP, texts, names, n);
192  PortTP.s = IPS_OK;
193  IDSetText(&PortTP, NULL);
194  return true;
195  }
196  }
197 
198  controller->ISNewText(dev, name, texts, names, n);
199 
200  return DefaultDevice::ISNewText(dev, name, texts, names, n);
201 }
202 
203 bool INDI::Focuser::ISSnoopDevice (XMLEle *root)
204 {
205  controller->ISSnoopDevice(root);
206 
208 }
209 
211 {
212  IUSaveConfigText(fp, &PortTP);
213  IUSaveConfigNumber(fp, &PresetNP);
214 
215  controller->saveConfigItems(fp);
216 
217  return true;
218 }
219 
220 void INDI::Focuser::buttonHelper(const char *button_n, ISState state, void *context)
221 {
222  static_cast<INDI::Focuser *>(context)->processButton(button_n, state);
223 }
224 
225 void INDI::Focuser::processButton(const char * button_n, ISState state)
226 {
227  //ignore OFF
228  if (state == ISS_OFF)
229  return;
230 
231  FocusTimerN[0].value = lastTimerValue;
232 
233  int rc=0;
234  // Focus In
235  if (!strcmp(button_n, "Focus In"))
236  {
237  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
238  {
239  FocusMotionS[FOCUS_INWARD].s = ISS_ON;
240  FocusMotionS[FOCUS_OUTWARD].s = ISS_OFF;
241  IDSetSwitch(&FocusMotionSP, NULL);
242  }
243 
244  if (capability.variableSpeed)
245  {
246  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
247  if (rc == 0)
248  FocusTimerNP.s = IPS_OK;
249  else if (rc == 1)
250  FocusTimerNP.s = IPS_BUSY;
251  else
252  FocusTimerNP.s = IPS_ALERT;
253 
254  IDSetNumber(&FocusTimerNP,NULL);
255  }
256  else if (capability.canRelMove)
257  {
258  rc=MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
259  if (rc == 0)
260  {
261  FocusRelPosNP.s=IPS_OK;
262  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int) FocusRelPosN[0].value);
263  IDSetNumber(&FocusAbsPosNP, NULL);
264  }
265  else if (rc == 1)
266  {
267  FocusRelPosNP.s=IPS_BUSY;
268  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int) FocusRelPosN[0].value);
269  }
270  }
271  }
272  else if (!strcmp(button_n, "Focus Out"))
273  {
274  if (FocusMotionS[FOCUS_OUTWARD].s != ISS_ON)
275  {
276  FocusMotionS[FOCUS_INWARD].s = ISS_OFF;
277  FocusMotionS[FOCUS_OUTWARD].s = ISS_ON;
278  IDSetSwitch(&FocusMotionSP, NULL);
279  }
280 
281  if (capability.variableSpeed)
282  {
283  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
284  if (rc == 0)
285  FocusTimerNP.s = IPS_OK;
286  else if (rc == 1)
287  FocusTimerNP.s = IPS_BUSY;
288  else
289  FocusTimerNP.s = IPS_ALERT;
290 
291  IDSetNumber(&FocusTimerNP,NULL);
292  }
293  else if (capability.canRelMove)
294  {
295  rc=MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
296  if (rc == 0)
297  {
298  FocusRelPosNP.s=IPS_OK;
299  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int) FocusRelPosN[0].value);
300  IDSetNumber(&FocusAbsPosNP, NULL);
301  }
302  else if (rc == 1)
303  {
304  FocusRelPosNP.s=IPS_BUSY;
305  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int) FocusRelPosN[0].value);
306  }
307  }
308  }
309 }
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indidriver.c:1346
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:79
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
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's auxiliary elements will be set to NULL...
Definition: indidriver.c:502
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minumum set of properties are defined t...
void IDSetText(const ITextVectorProperty *t, const char *msg,...)
Tell client to update an existing text vector property.
Definition: indidriver.c:1699
void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...)
Tell client to update an existing switch vector property.
Definition: indidriver.c:1779
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:209
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:300
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:263
Definition: indiapi.h:140
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1739
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL...
Definition: indidriver.c:419
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidriver.c:1327
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minumum set of properties are defined t...
Definition: indifocuser.cpp:68
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL...
Definition: indidriver.c:367
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's auxiliary elements will be set to NULL...
Definition: indidriver.c:398
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1187
Class to provide general functionality of a focuser device.
Definition: indifocuser.h:37
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...
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:106
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's auxiliary elements will be set to NULL...
Definition: indidriver.c:460
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's auxiliary elements will be set to NULL...
Definition: indidriver.c:525
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.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.