Instrument Neutral Distributed Interface INDI  2.0.2
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 
63 
64  controller->mapController("Focus In", "Focus In", Controller::CONTROLLER_BUTTON, "BUTTON_1");
65  controller->mapController("Focus Out", "Focus Out", Controller::CONTROLLER_BUTTON, "BUTTON_2");
66  controller->mapController("Abort Focus", "Abort Focus", Controller::CONTROLLER_BUTTON, "BUTTON_3");
67 
69 
71 
72  if (focuserConnection & CONNECTION_SERIAL)
73  {
76  {
77  return callHandshake();
78  });
80  }
81 
82  if (focuserConnection & CONNECTION_TCP)
83  {
84  tcpConnection = new Connection::TCP(this);
86  {
87  return callHandshake();
88  });
90  }
91 
92  return true;
93 }
94 
95 void Focuser::ISGetProperties(const char *dev)
96 {
97  // First we let our parent populate
99 
101  return;
102 }
103 
105 {
107 
108  if (isConnected())
109  {
110  if (CanAbsMove())
111  {
114  }
115  }
116  else
117  {
118  if (CanAbsMove())
119  {
122  }
123  }
124 
126  return true;
127 }
128 
129 bool Focuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
130 {
131  // first check if it's for our device
132  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
133  {
134  if (!strcmp(name, PresetNP.name))
135  {
136  IUUpdateNumber(&PresetNP, values, names, n);
137  PresetNP.s = IPS_OK;
138  IDSetNumber(&PresetNP, nullptr);
139 
140  //saveConfig();
141 
142  return true;
143  }
144 
145  if (strstr(name, "FOCUS_"))
146  return FI::processNumber(dev, name, values, names, n);
147  }
148 
149  return DefaultDevice::ISNewNumber(dev, name, values, names, n);
150 }
151 
152 bool Focuser::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
153 {
154  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
155  {
156  if (!strcmp(PresetGotoSP.name, name))
157  {
158  IUUpdateSwitch(&PresetGotoSP, states, names, n);
159  int index = IUFindOnSwitchIndex(&PresetGotoSP);
160 
161  if (PresetN[index].value < FocusAbsPosN[0].min)
162  {
164  IDSetSwitch(&PresetGotoSP, nullptr);
166  "Requested position out of bound. Focus minimum position is %g", FocusAbsPosN[0].min);
167  return true;
168  }
169  else if (PresetN[index].value > FocusAbsPosN[0].max)
170  {
172  IDSetSwitch(&PresetGotoSP, nullptr);
174  "Requested position out of bound. Focus maximum position is %g", FocusAbsPosN[0].max);
175  return true;
176  }
177 
178  IPState rc = MoveAbsFocuser(PresetN[index].value);
179  if (rc != IPS_ALERT)
180  {
182  DEBUGF(Logger::DBG_SESSION, "Moving to Preset %d with position %g.", index + 1,
183  PresetN[index].value);
184  IDSetSwitch(&PresetGotoSP, nullptr);
185 
187  IDSetNumber(&FocusAbsPosNP, nullptr);
188  return true;
189  }
190 
192  IDSetSwitch(&PresetGotoSP, nullptr);
193  return true;
194  }
195 
196  if (strstr(name, "FOCUS_"))
197  return FI::processSwitch(dev, name, states, names, n);
198  }
199 
200  controller->ISNewSwitch(dev, name, states, names, n);
201 
202  // Nobody has claimed this, so, ignore it
203  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
204 }
205 
206 bool Focuser::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
207 {
208  controller->ISNewText(dev, name, texts, names, n);
209 
210  return DefaultDevice::ISNewText(dev, name, texts, names, n);
211 }
212 
214 {
215  controller->ISSnoopDevice(root);
216 
217  return DefaultDevice::ISSnoopDevice(root);
218 }
219 
221 {
222  return false;
223 }
224 
226 {
228 
230 
233 
234  return true;
235 }
236 
237 void Focuser::buttonHelper(const char *button_n, ISState state, void *context)
238 {
239  static_cast<Focuser *>(context)->processButton(button_n, state);
240 }
241 
242 void Focuser::processButton(const char *button_n, ISState state)
243 {
244  //ignore OFF
245  if (state == ISS_OFF)
246  return;
247 
248  FocusTimerN[0].value = lastTimerValue;
249 
250  IPState rc = IPS_IDLE;
251 
252  // Abort
253  if (!strcmp(button_n, "Abort Focus"))
254  {
255  if (AbortFocuser())
256  {
258  DEBUG(Logger::DBG_SESSION, "Focuser aborted.");
259  if (CanAbsMove() && FocusAbsPosNP.s != IPS_IDLE)
260  {
262  IDSetNumber(&FocusAbsPosNP, nullptr);
263  }
264  if (CanRelMove() && FocusRelPosNP.s != IPS_IDLE)
265  {
267  IDSetNumber(&FocusRelPosNP, nullptr);
268  }
269  }
270  else
271  {
273  DEBUG(Logger::DBG_ERROR, "Aborting focuser failed.");
274  }
275 
276  IDSetSwitch(&FocusAbortSP, nullptr);
277  }
278  // Focus In
279  else if (!strcmp(button_n, "Focus In"))
280  {
281  if (FocusMotionS[FOCUS_INWARD].s != ISS_ON)
282  {
285  IDSetSwitch(&FocusMotionSP, nullptr);
286  }
287 
288  if (CanRelMove())
289  {
290  rc = MoveRelFocuser(FOCUS_INWARD, FocusRelPosN[0].value);
291  if (rc == IPS_OK)
292  {
294  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps inward", (int)FocusRelPosN[0].value);
295  IDSetNumber(&FocusAbsPosNP, nullptr);
296  }
297  else if (rc == IPS_BUSY)
298  {
300  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps inward...", (int)FocusRelPosN[0].value);
301  }
302  }
303  else if (HasVariableSpeed())
304  {
305  rc = MoveFocuser(FOCUS_INWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
306  FocusTimerNP.s = rc;
307  IDSetNumber(&FocusTimerNP, nullptr);
308  }
309 
310  }
311  else if (!strcmp(button_n, "Focus Out"))
312  {
314  {
317  IDSetSwitch(&FocusMotionSP, nullptr);
318  }
319 
320  if (CanRelMove())
321  {
322  rc = MoveRelFocuser(FOCUS_OUTWARD, FocusRelPosN[0].value);
323  if (rc == IPS_OK)
324  {
326  IDSetNumber(&FocusRelPosNP, "Focuser moved %d steps outward", (int)FocusRelPosN[0].value);
327  IDSetNumber(&FocusAbsPosNP, nullptr);
328  }
329  else if (rc == IPS_BUSY)
330  {
332  IDSetNumber(&FocusAbsPosNP, "Focuser is moving %d steps outward...", (int)FocusRelPosN[0].value);
333  }
334  }
335  else if (HasVariableSpeed())
336  {
337  rc = MoveFocuser(FOCUS_OUTWARD, FocusSpeedN[0].value, FocusTimerN[0].value);
338  FocusTimerNP.s = rc;
339  IDSetNumber(&FocusTimerNP, nullptr);
340  }
341  }
342 }
343 
344 bool Focuser::callHandshake()
345 {
346  if (focuserConnection > 0)
347  {
350  else if (getActiveConnection() == tcpConnection)
352  }
353 
354  return Handshake();
355 }
356 
357 void Focuser::setSupportedConnections(const uint8_t &value)
358 {
360 
361  if (value == 0 || (mask & value) == 0)
362  {
363  DEBUGF(Logger::DBG_ERROR, "Invalid connection mode %d", value);
364  return;
365  }
366 
367  focuserConnection = value;
368 }
369 
370 bool Focuser::SetFocuserMaxPosition(uint32_t ticks)
371 {
372  SyncPresets(ticks);
373  return true;
374 }
375 
376 void Focuser::SyncPresets(uint32_t ticks)
377 {
378  PresetN[0].max = ticks;
379  PresetN[0].step = PresetN[0].max / 50.0;
380  PresetN[1].max = ticks;
381  PresetN[1].step = PresetN[0].max / 50.0;
382  PresetN[2].max = ticks;
383  PresetN[2].step = PresetN[0].max / 50.0;
385 }
386 }
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
The TCP class manages connection with devices over the network via TCP/IP. Upon successfull connectio...
Definition: connectiontcp.h:38
int getPortFD() const
Definition: connectiontcp.h:84
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
The Controller class provides functionality to access a controller (e.g. joystick) input and send it ...
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected.
virtual bool ISSnoopDevice(XMLEle *root)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
void mapController(const char *propertyName, const char *propertyLabel, ControllerType type, const char *initialValue)
mapController adds a new property to the joystick's settings.
virtual bool initProperties()
virtual bool saveConfigItems(FILE *fp)
virtual void ISGetProperties(const char *dev)
virtual bool updateProperties()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
void addPollPeriodControl()
Add Polling period control to the driver.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
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 deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Connection::Interface * getActiveConnection()
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
Provides interface to implement focuser functionality.
ISwitchVectorProperty FocusMotionSP
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
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.
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
INumberVectorProperty FocusTimerNP
void initProperties(const char *groupName)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
virtual bool AbortFocuser()
AbortFocuser all focus motion.
ISwitchVectorProperty FocusAbortSP
virtual IPState MoveAbsFocuser(uint32_t targetTicks)
MoveFocuser the focuser to an absolute position.
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void processButton(const char *button_n, ISState state)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
ISwitchVectorProperty PresetGotoSP
Definition: indifocuser.h:110
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: indifocuser.cpp:95
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
INumber PresetN[3]
Definition: indifocuser.h:107
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:42
Connection::TCP * tcpConnection
Definition: indifocuser.h:117
INumberVectorProperty PresetNP
Definition: indifocuser.h:108
virtual ~Focuser()
Definition: indifocuser.cpp:37
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual void SyncPresets(uint32_t ticks)
syncPresets Updates the min/max/step range of the preset as per the maximum name of Absolute Focus Tr...
Connection::Serial * serialConnection
Definition: indifocuser.h:116
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Controller * controller
Definition: indifocuser.h:114
ISwitch PresetGotoS[3]
Definition: indifocuser.h:109
static void buttonHelper(const char *button_n, ISState state, void *context)
void setSupportedConnections(const uint8_t &value)
setConnection Set Focuser connection mode. Child class should call this in the constructor before Foc...
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
virtual bool Handshake()
perform handshake with device to check communication
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
double max(void)
double min(void)
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
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: indidevapi.c:272
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidevapi.c:15
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: indidevapi.c:158
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: indidevapi.c:180
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: indidevapi.c:235
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
Definition: indidriver.c:1296
#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:61
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
Namespace to encapsulate INDI client, drivers, and mediator classes.
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371