Instrument Neutral Distributed Interface INDI  2.0.2
lx200_16.cpp
Go to the documentation of this file.
1 /*
2  LX200 16"
3  Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
21 #include "lx200_16.h"
22 
23 #include "indicom.h"
24 #include "lx200driver.h"
25 
26 #include <cmath>
27 #include <cstring>
28 #include <unistd.h>
29 
30 #define LX16_TAB "GPS/16 inch Features"
31 
33 {
35 }
36 
38 {
39  return "LX200 16";
40 }
41 
43 {
45 
46  IUFillSwitch(&FanStatusS[0], "On", "", ISS_OFF);
47  IUFillSwitch(&FanStatusS[1], "Off", "", ISS_OFF);
49  IPS_IDLE);
50 
51  IUFillSwitch(&HomeSearchS[0], "Save Home", "", ISS_OFF);
52  IUFillSwitch(&HomeSearchS[1], "Set Home", "", ISS_OFF);
54  IPS_IDLE);
55 
56  IUFillSwitch(&FieldDeRotatorS[0], "On", "", ISS_OFF);
57  IUFillSwitch(&FieldDeRotatorS[1], "Off", "", ISS_OFF);
59  ISR_1OFMANY, 0, IPS_IDLE);
60 
61  IUFillNumber(&HorizontalCoordsN[0], "ALT", "Alt D:M:S", "%10.6m", -90., 90.0, 0.0, 0);
62  IUFillNumber(&HorizontalCoordsN[1], "AZ", "Az D:M:S", "%10.6m", 0.0, 360.0, 0.0, 0);
64  "Horizontal Coord", MAIN_CONTROL_TAB, IP_RW, 0, IPS_IDLE);
65 
66  return true;
67 }
68 
69 void LX200_16::ISGetProperties(const char *dev)
70 {
71  if (dev != nullptr && strcmp(dev, getDeviceName()) != 0)
72  return;
73 
74  // process parent first
76 
77  /*
78  if (isConnected())
79  {
80  defineProperty(&HorizontalCoordsNP);
81  defineProperty(&FanStatusSP);
82  defineProperty(&HomeSearchSP);
83  defineProperty(&FieldDeRotatorSP);
84  }
85  */
86 }
87 
89 {
90  // process parent first
92 
93  if (isConnected())
94  {
99  }
100  else
101  {
106  }
107 
108  return true;
109 }
110 
111 bool LX200_16::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
112 {
113  double newAlt = 0, newAz = 0;
114 
115  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
116  {
117  if (!strcmp(name, HorizontalCoordsNP.name))
118  {
119  int i = 0, nset = 0;
120 
121  for (nset = i = 0; i < n; i++)
122  {
123  INumber *horp = IUFindNumber(&HorizontalCoordsNP, names[i]);
124  if (horp == &HorizontalCoordsN[0])
125  {
126  newAlt = values[i];
127  nset += newAlt >= -90. && newAlt <= 90.0;
128  }
129  else if (horp == &HorizontalCoordsN[1])
130  {
131  newAz = values[i];
132  nset += newAz >= 0. && newAz <= 360.0;
133  }
134  }
135 
136  if (nset == 2)
137  {
138  if (!isSimulation() && (setObjAz(PortFD, newAz) < 0 || setObjAlt(PortFD, newAlt) < 0))
139  {
141  IDSetNumber(&HorizontalCoordsNP, "Error setting Alt/Az.");
142  return false;
143  }
144  targetAZ = newAz;
145  targetALT = newAlt;
146 
147  return handleAltAzSlew();
148  }
149  else
150  {
152  IDSetNumber(&HorizontalCoordsNP, "Altitude or Azimuth missing or invalid");
153  return false;
154  }
155  }
156  }
157 
158  LX200GPS::ISNewNumber(dev, name, values, names, n);
159  return true;
160 }
161 
162 bool LX200_16::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
163 {
164  int index = 0;
165 
166  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
167  {
168  if (!strcmp(name, FanStatusSP.name))
169  {
171  IUUpdateSwitch(&FanStatusSP, states, names, n);
173 
174  if (index == 0)
175  {
176  if (turnFanOn(PortFD) < 0)
177  {
179  IDSetSwitch(&FanStatusSP, "Error changing fan status.");
180  return false;
181  }
182  }
183  else
184  {
185  if (turnFanOff(PortFD) < 0)
186  {
188  IDSetSwitch(&FanStatusSP, "Error changing fan status.");
189  return false;
190  }
191  }
192 
193  FanStatusSP.s = IPS_OK;
194  IDSetSwitch(&FanStatusSP, index == 0 ? "Fan is ON" : "Fan is OFF");
195  return true;
196  }
197 
198  if (!strcmp(name, HomeSearchSP.name))
199  {
200  int ret = 0;
201 
203  IUUpdateSwitch(&HomeSearchSP, states, names, n);
205 
206  if (index == 0)
207  ret = seekHomeAndSave(PortFD);
208  else
209  ret = seekHomeAndSet(PortFD);
210 
211  INDI_UNUSED(ret);
213  IDSetSwitch(&HomeSearchSP, index == 0 ? "Seek Home and Save" : "Seek Home and Set");
214  return true;
215  }
216 
217  if (!strcmp(name, FieldDeRotatorSP.name))
218  {
219  int ret = 0;
220 
222  IUUpdateSwitch(&FieldDeRotatorSP, states, names, n);
224 
225  if (index == 0)
227  else
229 
230  INDI_UNUSED(ret);
232  IDSetSwitch(&FieldDeRotatorSP, index == 0 ? "Field deRotator is ON" : "Field deRotator is OFF");
233  return true;
234  }
235  }
236 
237  return LX200GPS::ISNewSwitch(dev, name, states, names, n);
238 }
239 
241 {
242  const struct timespec timeout = {0, 100000000L};
243  char altStr[64], azStr[64];
244 
246  {
247  abortSlew(PortFD);
248 
249  // sleep for 100 mseconds
250  nanosleep(&timeout, nullptr);
251  }
252 
253  if (!isSimulation() && slewToAltAz(PortFD))
254  {
256  IDSetNumber(&HorizontalCoordsNP, "Slew is not possible.");
257  return false;
258  }
259 
261  fs_sexa(azStr, targetAZ, 2, 3600);
262  fs_sexa(altStr, targetALT, 2, 3600);
263 
265  IDSetNumber(&HorizontalCoordsNP, "Slewing to Alt %s - Az %s", altStr, azStr);
266  return true;
267 }
268 
270 {
271  int searchResult = 0;
272  double dx, dy;
273 
275 
276  switch (HomeSearchSP.s)
277  {
278  case IPS_IDLE:
279  break;
280 
281  case IPS_BUSY:
282 
283  if (isSimulation())
284  searchResult = 1;
285  else if (getHomeSearchStatus(PortFD, &searchResult) < 0)
286  {
288  IDSetSwitch(&HomeSearchSP, "Error updating home search status.");
289  return false;
290  }
291 
292  if (searchResult == 0)
293  {
295  IDSetSwitch(&HomeSearchSP, "Home search failed.");
296  }
297  else if (searchResult == 1)
298  {
300  IDSetSwitch(&HomeSearchSP, "Home search successful.");
301  }
302  else if (searchResult == 2)
303  IDSetSwitch(&HomeSearchSP, "Home search in progress...");
304  else
305  {
307  IDSetSwitch(&HomeSearchSP, "Home search error.");
308  }
309  break;
310 
311  case IPS_OK:
312  break;
313  case IPS_ALERT:
314  break;
315  }
316 
317  switch (HorizontalCoordsNP.s)
318  {
319  case IPS_IDLE:
320  break;
321 
322  case IPS_BUSY:
323 
324  if (isSimulation())
325  {
326  currentAZ = targetAZ;
327  currentALT = targetALT;
329  return true;
330  }
331  if (getLX200Az(PortFD, &currentAZ) < 0 || getLX200Alt(PortFD, &currentALT) < 0)
332  {
334  IDSetNumber(&HorizontalCoordsNP, "Error getting Alt/Az.");
335  return false;
336  }
337 
338  dx = targetAZ - currentAZ;
339  dy = targetALT - currentALT;
340 
341  HorizontalCoordsNP.np[0].value = currentALT;
342  HorizontalCoordsNP.np[1].value = currentAZ;
343 
344  // accuracy threshold (3'), can be changed as desired.
345  if (fabs(dx) <= 0.05 && fabs(dy) <= 0.05)
346  {
348  currentAZ = targetAZ;
349  currentALT = targetALT;
350  IDSetNumber(&HorizontalCoordsNP, "Slew is complete.");
351  }
352  else
353  IDSetNumber(&HorizontalCoordsNP, nullptr);
354  break;
355 
356  case IPS_OK:
357  break;
358 
359  case IPS_ALERT:
360  break;
361  }
362 
363  return true;
364 }
365 
367 {
369 
370  if (!isSimulation())
371  {
372  getLX200Az(PortFD, &currentAZ);
373  getLX200Alt(PortFD, &currentALT);
374  HorizontalCoordsNP.np[0].value = currentALT;
375  HorizontalCoordsNP.np[1].value = currentAZ;
376  IDSetNumber(&HorizontalCoordsNP, nullptr);
377  }
378 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
bool isSimulation() const
TelescopeStatus TrackState
virtual void getBasicData() override
bool updateProperties()
Called when connected state changes, to add/remove properties.
Definition: lx200gps.cpp:117
void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: lx200gps.cpp:92
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
Definition: lx200gps.cpp:151
bool initProperties()
Called to initialize basic properties required all the time.
Definition: lx200gps.cpp:40
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ReadScopeStatus() override
Read telescope status.
ISwitch FanStatusS[2]
Definition: lx200_16.h:49
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
Definition: lx200_16.cpp:162
bool handleAltAzSlew()
Definition: lx200_16.cpp:240
INumber HorizontalCoordsN[2]
Definition: lx200_16.h:52
bool initProperties()
Called to initialize basic properties required all the time.
Definition: lx200_16.cpp:42
const char * getDefaultName()
Definition: lx200_16.cpp:37
LX200_16()
Definition: lx200_16.cpp:32
void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: lx200_16.cpp:69
bool ReadScopeStatus()
Read telescope status.
Definition: lx200_16.cpp:269
ISwitchVectorProperty HomeSearchSP
Definition: lx200_16.h:45
ISwitchVectorProperty FieldDeRotatorSP
Definition: lx200_16.h:42
ISwitch HomeSearchS[2]
Definition: lx200_16.h:46
ISwitchVectorProperty FanStatusSP
Definition: lx200_16.h:48
INumberVectorProperty HorizontalCoordsNP
Definition: lx200_16.h:51
void getBasicData()
Definition: lx200_16.cpp:366
ISwitch FieldDeRotatorS[2]
Definition: lx200_16.h:43
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Definition: lx200_16.cpp:111
bool updateProperties()
Called when connected state changes, to add/remove properties.
Definition: lx200_16.cpp:88
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ IP_RW
Definition: indiapi.h:186
@ 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
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string. sprint the variable a in sexagesimal format into out[].
Definition: indicom.c:141
Implementations for common driver routines.
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
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition: indidevapi.c:66
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
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
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
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
#define LX16_TAB
Definition: lx200_16.cpp:30
int setObjAlt(int fd, double alt)
int getHomeSearchStatus(int fd, int *status)
int setObjAz(int fd, double az)
int abortSlew(int fd)
#define seekHomeAndSave(fd)
Definition: lx200driver.h:170
#define turnFanOff(fd)
Definition: lx200driver.h:169
#define turnFieldDeRotatorOn(fd)
Definition: lx200driver.h:172
#define turnFieldDeRotatorOff(fd)
Definition: lx200driver.h:173
#define getLX200Alt(fd, x)
Definition: lx200driver.h:124
#define seekHomeAndSet(fd)
Definition: lx200driver.h:171
#define getLX200Az(fd, x)
Definition: lx200driver.h:125
#define slewToAltAz(fd)
Definition: lx200driver.h:164
#define turnFanOn(fd)
Definition: lx200driver.h:168
One number descriptor.
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371