Instrument Neutral Distributed Interface INDI  1.6.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 
27 namespace INDI
28 {
29 
31 {
32  controller = new Controller(this);
33 
35 }
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  IUFillNumber(&PresetN[0], "PRESET_1", "Preset 1", "%.f", 0, 100000, 1000, 0);
50  IUFillNumber(&PresetN[1], "PRESET_2", "Preset 2", "%.f", 0, 100000, 1000, 0);
51  IUFillNumber(&PresetN[2], "PRESET_3", "Preset 3", "%.f", 0, 100000, 1000, 0);
52  IUFillNumberVector(&PresetNP, PresetN, 3, getDeviceName(), "Presets", "", "Presets", IP_RW, 0, IPS_IDLE);
53 
54  //Preset GOTO
55  IUFillSwitch(&PresetGotoS[0], "Preset 1", "", ISS_OFF);
56  IUFillSwitch(&PresetGotoS[1], "Preset 2", "", ISS_OFF);
57  IUFillSwitch(&PresetGotoS[2], "Preset 3", "", ISS_OFF);
58  IUFillSwitchVector(&PresetGotoSP, PresetGotoS, 3, getDeviceName(), "Goto", "", "Presets", IP_RW, ISR_1OFMANY, 0,
59  IPS_IDLE);
60 
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  {
74  serialConnection->registerHandshake([&]() { return callHandshake(); });
76  }
77 
78  if (focuserConnection & CONNECTION_TCP)
79  {
80  tcpConnection = new Connection::TCP(this);
81  tcpConnection->registerHandshake([&]() { return callHandshake(); });
83  }
84 
85  return true;
86 }
87 
88 void Focuser::ISGetProperties(const char *dev)
89 {
90  // First we let our parent populate
92 
94  return;
95 }
96 
98 {
99  if (isConnected())
100  {
101  // Now we add our focusser specific stuff
103 
104  if (HasVariableSpeed())
105  {
108  }
109  if (CanRelMove())
111  if (CanAbsMove())
113  if (CanAbort())
115  if (CanAbsMove())
116  {
119  }
120  }
121  else
122  {
124  if (HasVariableSpeed())
125  {
128  }
129  if (CanRelMove())
131  if (CanAbsMove())
133  if (CanAbort())
135  if (CanAbsMove())
136  {
139  }
140  }
141 
143  return true;
144 }
145 
146 bool Focuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
147 {
148  // first check if it's for our device
149  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
150  {
151  if (!strcmp(name, PresetNP.name))
152  {
153  IUUpdateNumber(&PresetNP, values, names, n);
154  PresetNP.s = IPS_OK;
155  IDSetNumber(&PresetNP, nullptr);
156 
157  //saveConfig();
158 
159  return true;
160  }
161 
162  if (strstr(name, "FOCUS_"))
163  return processFocuserNumber(dev, name, values, names, n);
164  }
165 
166  return DefaultDevice::ISNewNumber(dev, name, values, names, n);
167 }
168 
169 bool Focuser::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
170 {
171  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
172  {
173  if (!strcmp(PresetGotoSP.name, name))
174  {
175  IUUpdateSwitch(&PresetGotoSP, states, names, n);
176  int index = IUFindOnSwitchIndex(&PresetGotoSP);
177 
178  if (PresetN[index].value < FocusAbsPosN[0].min)
179  {
181  IDSetSwitch(&PresetGotoSP, nullptr);
183  "Requested position out of bound. Focus minimum position is %g", FocusAbsPosN[0].min);
184  return true;
185  }
186  else if (PresetN[index].value > FocusAbsPosN[0].max)
187  {
189  IDSetSwitch(&PresetGotoSP, nullptr);
191  "Requested position out of bound. Focus maximum position is %g", FocusAbsPosN[0].max);
192  return true;
193  }
194 
195  int rc = MoveAbsFocuser(PresetN[index].value);
196  if (rc >= 0)
197  {
199  DEBUGF(Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index + 1,
200  PresetN[index].value);
201  IDSetSwitch(&PresetGotoSP, nullptr);
202  return true;
203  }
204 
206  IDSetSwitch(&PresetGotoSP, nullptr);
207  return true;
208  }
209 
210  if (strstr(name, "FOCUS_"))
211  return processFocuserSwitch(dev, name, states, names, n);
212  }
213 
214  controller->ISNewSwitch(dev, name, states, names, n);
215 
216  // Nobody has claimed this, so, ignore it
217  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
218 }
219 
220 bool Focuser::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
221 {
222  controller->ISNewText(dev, name, texts, names, n);
223 
224  return DefaultDevice::ISNewText(dev, name, texts, names, n);
225 }
226 
228 {
229  controller->ISSnoopDevice(root);
230 
231  return DefaultDevice::ISSnoopDevice(root);
232 }
233 
235 {
236  return false;
237 }
238 
240 {
242 
244 
246 
247  return true;
248 }
249 
250 void Focuser::buttonHelper(const char *button_n, ISState state, void *context)
251 {
252  static_cast<Focuser *>(context)->processButton(button_n, state);
253 }
254 
255 void Focuser::processButton(const char *button_n, ISState state)
256 {
257  //ignore OFF
258  if (state == ISS_OFF)
259  return;
260 
262 
263  IPState rc = IPS_IDLE;
264 
265  // Abort
266  if (!strcmp(button_n, "Abort Focus"))
267  {
268  if (AbortFocuser())
269  {
270  AbortSP.s = IPS_OK;
271  DEBUG(Logger::DBG_SESSION, "Focuser aborted.");
272  if (CanAbsMove() && FocusAbsPosNP.s != IPS_IDLE)
273  {
275  IDSetNumber(&FocusAbsPosNP, nullptr);
276  }
277  if (CanRelMove() && FocusRelPosNP.s != IPS_IDLE)
278  {
280  IDSetNumber(&FocusRelPosNP, nullptr);
281  }
282  }
283  else
284  {
285  AbortSP.s = IPS_ALERT;
286  DEBUG(Logger::DBG_ERROR, "Aborting focuser failed.");
287  }
288 
289  IDSetSwitch(&AbortSP, nullptr);
290  }
291  // Focus In
292  else if (!strcmp(button_n, "Focus In"))
293  {
294  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
295  {
298  IDSetSwitch(&FocusMotionSP, nullptr);
299  }
300 
301  if (HasVariableSpeed())
302  {
303  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
304  FocusTimerNP.s = rc;
305  IDSetNumber(&FocusTimerNP, nullptr);
306  }
307  else if (CanRelMove())
308  {
309  rc = MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
310  if (rc == IPS_OK)
311  {
313  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int)FocusRelPosN[0].value);
314  IDSetNumber(&FocusAbsPosNP, nullptr);
315  }
316  else if (rc == IPS_BUSY)
317  {
319  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int)FocusRelPosN[0].value);
320  }
321  }
322  }
323  else if (!strcmp(button_n, "Focus Out"))
324  {
326  {
329  IDSetSwitch(&FocusMotionSP, nullptr);
330  }
331 
332  if (HasVariableSpeed())
333  {
334  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
335  FocusTimerNP.s = rc;
336  IDSetNumber(&FocusTimerNP, nullptr);
337  }
338  else if (CanRelMove())
339  {
340  rc = MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
341  if (rc == IPS_OK)
342  {
344  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int)FocusRelPosN[0].value);
345  IDSetNumber(&FocusAbsPosNP, nullptr);
346  }
347  else if (rc == IPS_BUSY)
348  {
350  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int)FocusRelPosN[0].value);
351  }
352  }
353  }
354 }
355 
356 bool Focuser::callHandshake()
357 {
358  if (focuserConnection > 0)
359  {
362  else if (getActiveConnection() == tcpConnection)
364  }
365 
366  return Handshake();
367 }
368 
370 {
371  return focuserConnection;
372 }
373 
374 void Focuser::setFocuserConnection(const uint8_t &value)
375 {
377 
378  if (value == 0 || (mask & value) == 0)
379  {
380  DEBUGF(Logger::DBG_ERROR, "Invalid connection mode %d", value);
381  return;
382  }
383 
384  focuserConnection = value;
385 }
386 }
int getPortFD() const
Definition: connectiontcp.h:68
virtual IPState MoveAbsFocuser(uint32_t targetTicks)
MoveFocuser the focuser to an absolute position.
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...
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected. ...
bool processFocuserNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
Connection::TCP * tcpConnection
Definition: indifocuser.h:102
INumberVectorProperty FocusTimerNP
virtual bool AbortFocuser()
AbortFocuser all focus motion.
Connection::Interface * getActiveConnection()
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
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
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.
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:336
void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...)
Tell client to update an existing switch vector property.
Definition: indidriver.c:1937
IPState
Property state.
Definition: indiapi.h:143
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...
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.
static void buttonHelper(const char *button_n, ISState state, void *context)
INumberVectorProperty FocusRelPosNP
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver...
Definition: indifocuser.cpp:97
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.
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
Definition: indiapi.h:167
const char * name
Definition: indiserver.c:113
INumberVectorProperty PresetNP
Definition: indifocuser.h:93
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1895
Namespace to encapsulate INDI client, drivers, and mediator classes. Developers can subclass the base...
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function...
Definition: indifocuser.cpp:42
char name[MAXINDINAME]
Definition: indiapi.h:304
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
void processButton(const char *button_n, ISState state)
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...
uint8_t getFocuserConnection() const
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
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:1458
void initFocuserProperties(const char *deviceName, const char *groupName)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
INumberVectorProperty FocusSpeedNP
Controller * controller
Definition: indifocuser.h:99
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:101
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
void setFocuserConnection(const uint8_t &value)
setFocuserConnection Set Focuser connection mode. Child class should call this in the constructor bef...
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:94
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1389
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
ISwitchVectorProperty PresetGotoSP
Definition: indifocuser.h:95
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:352
virtual bool saveConfigItems(FILE *fp)
virtual bool Handshake()
perform handshake with device to check communication
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
const char * getDeviceName()
bool processFocuserSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
virtual bool ISSnoopDevice(XMLEle *root)
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:88
ISwitchVectorProperty AbortSP
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function...
ISState
Switch state.
Definition: indiapi.h:134
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
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file ...
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
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
virtual ~Focuser()
Definition: indifocuser.cpp:37
void defineNumber(INumberVectorProperty *nvp)
Define number vector to client & register it. Alternatively, IDDefNumber can be used but the property...
INumber PresetN[3]
Definition: indifocuser.h:92
double value
Definition: indiapi.h:271