Instrument Neutral Distributed Interface INDI  2.0.2
lx200fs2.cpp
Go to the documentation of this file.
1 /*
2  Astro-Electronic FS-2 Driver
3  Copyright (C) 2015 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 #include "lx200fs2.h"
21 
22 #include "indicom.h"
23 
24 #include <libnova/transform.h>
25 
26 #include <cmath>
27 #include <cstring>
28 
30 {
31  setVersion(2, 2);
32 
35 }
36 
38 {
40 
41  IUFillNumber(&SlewAccuracyN[0], "SlewRA", "RA (arcmin)", "%10.6m", 0., 60., 1., 3.0);
42  IUFillNumber(&SlewAccuracyN[1], "SlewDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
45  IUFillSwitchVector(&StopAfterParkSP, StopAfterParkS, 2, getDeviceName(), "Stop after Park", "Stop after Park", OPTIONS_TAB,
47  IUFillSwitch(&StopAfterParkS[0], "ON", "ON", ISS_OFF);
48  IUFillSwitch(&StopAfterParkS[1], "OFF", "OFF", ISS_ON);
49 
51 
52  return true;
53 }
54 
56 {
58 
59  if (isConnected())
60  {
64 
65  if (InitPark())
66  {
67  // If loading parking data is successful, we just set the default parking values.
70 
71  if (isParked())
72  {
73  // Force tracking to stop at startup.
75  TrackingStop();
76  }
77  }
78  else
79  {
80  // Otherwise, we set all parking data to default in case no parking data is found.
81  SetAxis1Park(0);
85  }
86  }
87  else
88  {
92  }
93 
94  return true;
95 }
96 
97 bool LX200FS2::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
98 {
99  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
100  {
101  if (!strcmp(name, SlewAccuracyNP.name))
102  {
103  if (IUUpdateNumber(&SlewAccuracyNP, values, names, n) < 0)
104  return false;
105 
107 
108  if (SlewAccuracyN[0].value < 3 || SlewAccuracyN[1].value < 3)
109  IDSetNumber(&SlewAccuracyNP, "Warning: Setting the slew accuracy too low may result in a dead lock");
110 
111  IDSetNumber(&SlewAccuracyNP, nullptr);
112  return true;
113  }
114  }
115 
116  return LX200Generic::ISNewNumber(dev, name, values, names, n);
117 }
118 
119 bool LX200FS2::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
120 {
121  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
122  {
123  if (!strcmp(name, StopAfterParkSP.name))
124  {
125  // Find out which state is requested by the client
126  const char *actionName = IUFindOnSwitchName(states, names, n);
127  // If switch is the same state as actionName, then we do nothing.
128  int currentIndex = IUFindOnSwitchIndex(&StopAfterParkSP);
129  if (!strcmp(actionName, StopAfterParkS[currentIndex].name))
130  {
131  DEBUGF(INDI::Logger::DBG_SESSION, "Stop After Park is already %s", StopAfterParkS[currentIndex].label);
134  return true;
135  }
136 
137  // Otherwise, let us update the switch state
138  IUUpdateSwitch(&StopAfterParkSP, states, names, n);
139  currentIndex = IUFindOnSwitchIndex(&StopAfterParkSP);
140  DEBUGF(INDI::Logger::DBG_SESSION, "Stop After Park is now %s", StopAfterParkS[currentIndex].label);
143  return true;
144  }
145  }
146 
147  return LX200Generic::ISNewSwitch(dev, name, states, names, n);
148 }
149 
151 {
152  return "Astro-Electronic FS-2";
153 }
154 
156 {
157  const double dx = targetRA - currentRA;
158  const double dy = targetDEC - currentDEC;
159  return fabs(dx) <= (SlewAccuracyN[0].value / (900.0)) && fabs(dy) <= (SlewAccuracyN[1].value / 60.0);
160 }
161 
163 {
164  return true;
165 }
166 
168 {
170 
173 
174  return true;
175 }
176 
178 {
179  double parkAz = GetAxis1Park();
180  double parkAlt = GetAxis2Park();
181 
182  char AzStr[16], AltStr[16];
183  fs_sexa(AzStr, parkAz, 2, 3600);
184  fs_sexa(AltStr, parkAlt, 2, 3600);
185  LOGF_DEBUG("Parking to Az (%s) Alt (%s)...", AzStr, AltStr);
186 
187  INDI::IEquatorialCoordinates equatorialCoords {0, 0};
188  INDI::IHorizontalCoordinates horizontalCoords {parkAz, parkAlt};
189  INDI::HorizontalToEquatorial(&horizontalCoords, &m_Location, ln_get_julian_from_sys(), &equatorialCoords);
190 
191  char RAStr[16], DEStr[16];
192  fs_sexa(RAStr, equatorialCoords.rightascension, 2, 3600);
193  fs_sexa(DEStr, equatorialCoords.declination, 2, 3600);
194  LOGF_DEBUG("Parking to RA (%s) DEC (%s)...", RAStr, DEStr);
195 
196  if (Goto(equatorialCoords.rightascension, equatorialCoords.declination))
197  {
199  LOG_INFO("Parking is in progress...");
200 
201  return true;
202  }
203  else
204  return false;
205 }
206 
208 {
209  if (ParkedStatus != PARKED_NOTPARKED) return;
210 
211  // Remember current slew rate
212  savedSlewRateIndex = static_cast <enum TelescopeSlewRate> (IUFindOnSwitchIndex(&SlewRateSP));
213 
216 }
217 
219 {
220  if (ParkedStatus != PARKED_NEEDABORT) return;
221 
222  Abort();
224 }
225 
227 {
228  if (ParkedStatus != PARKED_NEEDSTOP) return;
229 
232 }
233 
235 {
236  if (ParkedStatus != PARKED_STOPPED) return;
237 
239 
241 }
242 
244 {
245  if (ParkedStatus != UNPARKED_NEEDSLEW) return;
246 
247  updateSlewRate(savedSlewRateIndex);
248 
250 }
251 
253 {
254  bool retval = LX200Generic::ReadScopeStatus();
255 
256  // For FS-2 v1.21 owners, stop tracking once Parked.
257  if (retval &&
258  StopAfterParkS[0].s == ISS_ON &&
259  isConnected() &&
260  !isSimulation())
261  {
262  switch (TrackState)
263  {
264  case SCOPE_PARKED:
265  // If you are changing state from parking to parked,
266  // kick off the motor-stopping state machine
267  switch (ParkedStatus)
268  {
269  case PARKED_NOTPARKED:
270  LOG_INFO("Mount at park position. Tracking stopping.");
271  TrackingStop();
272  break;
273  case PARKED_NEEDABORT:
274  LOG_INFO("Mount at 1x sidereal.");
276  break;
277  case PARKED_NEEDSTOP:
278  LOG_INFO("Mount is parked, motors stopped.");
280  break;
281  case PARKED_STOPPED:
282  default:
283  break;
284 
285  }
286  break;
287  case SCOPE_IDLE:
288  // If you are changing state from parked to tracking,
289  // kick off the motor-starting state machine
290  switch (ParkedStatus)
291  {
292  case UNPARKED_NEEDSLEW:
293  LOG_INFO("Mount is unparked, restoring slew rate.");
295  break;
296  default:
297  break;
298 
299  }
300  break;
301  default:
302  break;
303  }
304  return true;
305  }
306 
307 
308  return retval;
309 }
310 
312 {
313  double parkAz = GetAxis1Park();
314  double parkAlt = GetAxis2Park();
315 
316  char AzStr[16], AltStr[16];
317  fs_sexa(AzStr, parkAz, 2, 3600);
318  fs_sexa(AltStr, parkAlt, 2, 3600);
319  LOGF_DEBUG("Unparking from Az (%s) Alt (%s)...", AzStr, AltStr);
320 
321  INDI::IEquatorialCoordinates equatorialCoords {0, 0};
322  INDI::IHorizontalCoordinates horizontalCoords {parkAz, parkAlt};
323  INDI::HorizontalToEquatorial(&horizontalCoords, &m_Location, ln_get_julian_from_sys(), &equatorialCoords);
324 
325  char RAStr[16], DEStr[16];
326  fs_sexa(RAStr, equatorialCoords.rightascension, 2, 3600);
327  fs_sexa(DEStr, equatorialCoords.declination, 2, 3600);
328  LOGF_DEBUG("Syncing to parked coordinates RA (%s) DEC (%s)...", RAStr, DEStr);
329 
330  if (Sync(equatorialCoords.rightascension, equatorialCoords.declination))
331  {
332  SetParked(false);
333  if (StopAfterParkS[0].s == ISS_ON)
334  {
335  TrackingStart();
336  }
337  return true;
338  }
339  else
340  return false;
341 }
342 
344 {
346  INDI::IHorizontalCoordinates horizontalCoords {0, 0};
347  INDI::EquatorialToHorizontal(&equatorialCoords, &m_Location, ln_get_julian_from_sys(), &horizontalCoords);
348  double parkAZ = horizontalCoords.azimuth;
349  double parkAlt = horizontalCoords.altitude;
350  char AzStr[16], AltStr[16];
351  fs_sexa(AzStr, parkAZ, 2, 3600);
352  fs_sexa(AltStr, parkAlt, 2, 3600);
353  LOGF_DEBUG("Setting current parking position to coordinates Az (%s) Alt (%s)...", AzStr, AltStr);
354  SetAxis1Park(parkAZ);
355  SetAxis2Park(parkAlt);
356  return true;
357 }
358 
360 {
361  // By defualt azimuth 0
362  SetAxis1Park(0);
363 
364  // Altitude = latitude of observer
366 
367  return true;
368 }
369 
370 bool LX200FS2::updateLocation(double latitude, double longitude, double elevation)
371 {
372  INDI_UNUSED(latitude);
373  INDI_UNUSED(longitude);
374  INDI_UNUSED(elevation);
375  return true;
376 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
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
void SetAxis1Park(double value)
SetRAPark Set current RA/AZ parking position. The data park file (stored in ~/.indi/ParkData....
void SetAxis1ParkDefault(double steps)
SetRAPark Set default RA/AZ parking position.
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
double GetAxis1Park() const
double GetAxis2Park() const
bool isParked()
isParked is mount currently parked?
ISwitchVectorProperty SlewRateSP
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
IGeographicCoordinates m_Location
INumber LocationN[3]
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
void SetAxis2Park(double steps)
SetDEPark Set current DEC/ALT parking position. The data park file (stored in ~/.indi/ParkData....
void SetParkDataType(TelescopeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
void SetAxis2ParkDefault(double steps)
SetDEParkDefault Set default DEC/ALT parking position.
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
Definition: lx200fs2.cpp:343
void TrackingStart_RestoreSlewRate()
Definition: lx200fs2.cpp:243
enum LX200FS2::TelescopeParkedStatus ParkedStatus
@ PARKED_STOPPED
Definition: lx200fs2.h:71
@ UNPARKED_NEEDSLEW
Definition: lx200fs2.h:72
@ PARKED_NEEDSTOP
Definition: lx200fs2.h:70
@ PARKED_NOTPARKED
Definition: lx200fs2.h:68
@ PARKED_NEEDABORT
Definition: lx200fs2.h:69
INumberVectorProperty SlewAccuracyNP
Definition: lx200fs2.h:60
void TrackingStart()
Definition: lx200fs2.cpp:234
void TrackingStop_Abort()
Definition: lx200fs2.cpp:218
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: lx200fs2.cpp:55
INumber SlewAccuracyN[2]
Definition: lx200fs2.h:59
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
Definition: lx200fs2.cpp:359
LX200FS2()
Definition: lx200fs2.cpp:29
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition: lx200fs2.cpp:37
virtual bool Park() override
Park the telescope to its home position.
Definition: lx200fs2.cpp:177
virtual bool checkConnection() override
Definition: lx200fs2.cpp:162
void TrackingStop()
Definition: lx200fs2.cpp:207
virtual bool ReadScopeStatus() override
Read telescope status.
Definition: lx200fs2.cpp:252
ISwitchVectorProperty StopAfterParkSP
Definition: lx200fs2.h:62
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
Definition: lx200fs2.cpp:370
virtual bool UnPark() override
Unpark the telescope if already parked.
Definition: lx200fs2.cpp:311
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: lx200fs2.cpp:119
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: lx200fs2.cpp:97
virtual const char * getDefaultName() override
Definition: lx200fs2.cpp:150
virtual bool isSlewComplete() override
Definition: lx200fs2.cpp:155
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: lx200fs2.cpp:167
void TrackingStop_AllStop()
Definition: lx200fs2.cpp:226
ISwitch StopAfterParkS[2]
Definition: lx200fs2.h:63
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
bool updateSlewRate(int index)
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool Goto(double ra, double dec) override
Move the scope to the supplied RA and DEC coordinates.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition: indiapi.h:500
@ IP_RW
Definition: indiapi.h:186
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_ATMOST1
Definition: indiapi.h:174
@ DIRECTION_EAST
Definition: indibasetypes.h:57
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 IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indidevapi.c:25
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
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
Definition: indidevapi.c:137
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
#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
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
void EquatorialToHorizontal(IEquatorialCoordinates *object, IGeographicCoordinates *observer, double JD, IHorizontalCoordinates *position)
EquatorialToHorizontal Calculate horizontal coordinates from equatorial coordinates.
Definition: libastro.cpp:140
void HorizontalToEquatorial(IHorizontalCoordinates *object, IGeographicCoordinates *observer, double JD, IEquatorialCoordinates *position)
HorizontalToEquatorial Calculate Equatorial EOD Coordinates from horizontal coordinates.
Definition: libastro.cpp:156
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371