Instrument Neutral Distributed Interface INDI 2.2.5
lx200fs2.cpp
Go to the documentation of this file.
1/*
2 Astro-Electronic FS-2 Driver
3 Copyright (C) 2015-2023 Jasem Mutlaq ([email protected])
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#include "lx200driver.h"
24
25#include <libnova/transform.h>
26
27#include <cmath>
28#include <cstring>
29
37
39{
41
42 IUFillNumber(&SlewAccuracyN[0], "SlewRA", "RA (arcmin)", "%10.6m", 0., 60., 1., 3.0);
43 IUFillNumber(&SlewAccuracyN[1], "SlewDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
46 IUFillSwitchVector(&StopAfterParkSP, StopAfterParkS, 2, getDeviceName(), "Stop after Park", "Stop after Park", OPTIONS_TAB,
48 IUFillSwitch(&StopAfterParkS[0], "ON", "ON", ISS_OFF);
49 IUFillSwitch(&StopAfterParkS[1], "OFF", "OFF", ISS_ON);
50
52
53 return true;
54}
55
57{
59
60 if (isConnected())
61 {
65
66 if (InitPark())
67 {
68 // If loading parking data is successful, we just set the default parking values.
71
72 if (isParked())
73 {
74 // Force tracking to stop at startup.
77 }
78 }
79 else
80 {
81 // Otherwise, we set all parking data to default in case no parking data is found.
82 SetAxis1Park(0);
86 }
87 }
88 else
89 {
93 }
94
95 return true;
96}
97
98bool LX200FS2::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
99{
100 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
101 {
102 if (!strcmp(name, SlewAccuracyNP.name))
103 {
104 if (IUUpdateNumber(&SlewAccuracyNP, values, names, n) < 0)
105 return false;
106
108
109 if (SlewAccuracyN[0].value < 3 || SlewAccuracyN[1].value < 3)
110 IDSetNumber(&SlewAccuracyNP, "Warning: Setting the slew accuracy too low may result in a dead lock");
111
112 IDSetNumber(&SlewAccuracyNP, nullptr);
113 return true;
114 }
115 }
116
117 return LX200Generic::ISNewNumber(dev, name, values, names, n);
118}
119
120bool LX200FS2::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
121{
122 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
123 {
124 if (!strcmp(name, StopAfterParkSP.name))
125 {
126 // Find out which state is requested by the client
127 const char *actionName = IUFindOnSwitchName(states, names, n);
128 // If switch is the same state as actionName, then we do nothing.
129 int currentIndex = IUFindOnSwitchIndex(&StopAfterParkSP);
130 if (!strcmp(actionName, StopAfterParkS[currentIndex].name))
131 {
132 DEBUGF(INDI::Logger::DBG_SESSION, "Stop After Park is already %s", StopAfterParkS[currentIndex].label);
135 return true;
136 }
137
138 // Otherwise, let us update the switch state
139 IUUpdateSwitch(&StopAfterParkSP, states, names, n);
140 currentIndex = IUFindOnSwitchIndex(&StopAfterParkSP);
141 DEBUGF(INDI::Logger::DBG_SESSION, "Stop After Park is now %s", StopAfterParkS[currentIndex].label);
144 return true;
145 }
146 }
147
148 return LX200Generic::ISNewSwitch(dev, name, states, names, n);
149}
150
152{
153 return "Astro-Electronic FS-2";
154}
155
157{
158 const double dx = targetRA - currentRA;
159 const double dy = targetDEC - currentDEC;
160 return fabs(dx) <= (SlewAccuracyN[0].value / (900.0)) && fabs(dy) <= (SlewAccuracyN[1].value / 60.0);
161}
162
164{
165 return true;
166}
167
169{
171
174
175 return true;
176}
177
179{
180 double parkAz = GetAxis1Park();
181 double parkAlt = GetAxis2Park();
182
183 char AzStr[16], AltStr[16];
184 fs_sexa(AzStr, parkAz, 2, 3600);
185 fs_sexa(AltStr, parkAlt, 2, 3600);
186 LOGF_DEBUG("Parking to Az (%s) Alt (%s)...", AzStr, AltStr);
187
188 INDI::IEquatorialCoordinates equatorialCoords {0, 0};
189 INDI::IHorizontalCoordinates horizontalCoords {parkAz, parkAlt};
190 INDI::HorizontalToEquatorial(&horizontalCoords, &m_Location, ln_get_julian_from_sys(), &equatorialCoords);
191
192 char RAStr[16], DEStr[16];
193 fs_sexa(RAStr, equatorialCoords.rightascension, 2, 3600);
194 fs_sexa(DEStr, equatorialCoords.declination, 2, 3600);
195 LOGF_DEBUG("Parking to RA (%s) DEC (%s)...", RAStr, DEStr);
196
197 if (Goto(equatorialCoords.rightascension, equatorialCoords.declination))
198 {
200 LOG_INFO("Parking is in progress...");
201
202 return true;
203 }
204 else
205 return false;
206}
207
209{
210 if (ParkedStatus != PARKED_NOTPARKED) return;
211
212 // Remember current slew rate
213 savedSlewRateIndex = static_cast <enum TelescopeSlewRate> (SlewRateSP.findOnSwitchIndex());
214
217}
218
226
234
243
245{
246 if (ParkedStatus != UNPARKED_NEEDSLEW) return;
247
248 updateSlewRate(savedSlewRateIndex);
249
251}
252
254{
255 bool retval = LX200Generic::ReadScopeStatus();
256
257 // For FS-2 v1.21 owners, stop tracking once Parked.
258 if (retval &&
259 StopAfterParkS[0].s == ISS_ON &&
260 isConnected() &&
261 !isSimulation())
262 {
263 switch (TrackState)
264 {
265 case SCOPE_PARKED:
266 // If you are changing state from parking to parked,
267 // kick off the motor-stopping state machine
268 switch (ParkedStatus)
269 {
270 case PARKED_NOTPARKED:
271 LOG_INFO("Mount at park position. Tracking stopping.");
272 TrackingStop();
273 break;
274 case PARKED_NEEDABORT:
275 LOG_INFO("Mount at 1x sidereal.");
277 break;
278 case PARKED_NEEDSTOP:
279 LOG_INFO("Mount is parked, motors stopped.");
281 break;
282 case PARKED_STOPPED:
283 default:
284 break;
285
286 }
287 break;
288 case SCOPE_IDLE:
289 // If you are changing state from parked to tracking,
290 // kick off the motor-starting state machine
291 switch (ParkedStatus)
292 {
294 LOG_INFO("Mount is unparked, restoring slew rate.");
296 break;
297 default:
298 break;
299
300 }
301 break;
302 default:
303 break;
304 }
305 return true;
306 }
307
308
309 return retval;
310}
311
313{
314 double parkAz = GetAxis1Park();
315 double parkAlt = GetAxis2Park();
316
317 char AzStr[16], AltStr[16];
318 fs_sexa(AzStr, parkAz, 2, 3600);
319 fs_sexa(AltStr, parkAlt, 2, 3600);
320 LOGF_DEBUG("Unparking from Az (%s) Alt (%s)...", AzStr, AltStr);
321
322 INDI::IEquatorialCoordinates equatorialCoords {0, 0};
323 INDI::IHorizontalCoordinates horizontalCoords {parkAz, parkAlt};
324 INDI::HorizontalToEquatorial(&horizontalCoords, &m_Location, ln_get_julian_from_sys(), &equatorialCoords);
325
326 char RAStr[16], DEStr[16];
327 fs_sexa(RAStr, equatorialCoords.rightascension, 2, 3600);
328 fs_sexa(DEStr, equatorialCoords.declination, 2, 3600);
329 LOGF_DEBUG("Syncing to parked coordinates RA (%s) DEC (%s)...", RAStr, DEStr);
330
331 if (Sync(equatorialCoords.rightascension, equatorialCoords.declination))
332 {
333 SetParked(false);
334 if (StopAfterParkS[0].s == ISS_ON)
335 {
337 }
338 return true;
339 }
340 else
341 return false;
342}
343
345{
347 INDI::IHorizontalCoordinates horizontalCoords {0, 0};
348 INDI::EquatorialToHorizontal(&equatorialCoords, &m_Location, ln_get_julian_from_sys(), &horizontalCoords);
349 double parkAZ = horizontalCoords.azimuth;
350 double parkAlt = horizontalCoords.altitude;
351 char AzStr[16], AltStr[16];
352 fs_sexa(AzStr, parkAZ, 2, 3600);
353 fs_sexa(AltStr, parkAlt, 2, 3600);
354 LOGF_DEBUG("Setting current parking position to coordinates Az (%s) Alt (%s)...", AzStr, AltStr);
355 SetAxis1Park(parkAZ);
356 SetAxis2Park(parkAlt);
357 return true;
358}
359
361{
362 // By default azimuth 0
363 SetAxis1Park(0);
364
365 // Altitude = latitude of observer
367
368 return true;
369}
370
371bool LX200FS2::updateLocation(double latitude, double longitude, double elevation)
372{
373 INDI_UNUSED(latitude);
374 INDI_UNUSED(longitude);
375 INDI_UNUSED(elevation);
376 return true;
377}
378
379bool LX200FS2::Goto(double r, double d)
380{
381 targetRA = r;
382 targetDEC = d;
383 char RAStr[64], DecStr[64];
384
385 fs_sexa(RAStr, targetRA, 2, 3600);
386 fs_sexa(DecStr, targetDEC, 2, 3600);
387
388
389 if (!isSimulation())
390 {
391 if (setObjectRA(PortFD, targetRA, true) < 0 || (setObjectDEC(PortFD, targetDEC, true)) < 0)
392 {
394 LOG_ERROR("Error setting RA/DEC.");
395 EqNP.apply();
396 return false;
397 }
398
399 if (Slew(PortFD))
400 {
402 LOGF_ERROR("Error Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
403 EqNP.apply();
404 slewError(1);
405 return false;
406 }
407 }
408
411
412 LOGF_INFO("Slewing to RA: %s - DEC: %s", RAStr, DecStr);
413 return true;
414}
415
416bool LX200FS2::Sync(double ra, double dec)
417{
418 if (!isSimulation())
419 {
420 if (setObjectRA(PortFD, ra, true) < 0 || setObjectDEC(PortFD, dec, true) < 0)
421 {
423 LOG_ERROR("Error setting RA/DEC. Unable to Sync.");
424 EqNP.apply();
425 return false;
426 }
427
428 char syncString[256];
429 if (::Sync(PortFD, syncString) < 0)
430 {
432 LOG_ERROR("Synchronization failed.");
433 EqNP.apply();
434 return false;
435 }
436
437 }
438
439 currentRA = ra;
440 currentDEC = dec;
441 LOG_INFO("Synchronization successful.");
444 return true;
445}
446
bool isConnected() const
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
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
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?
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
IGeographicCoordinates m_Location
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
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:344
void TrackingStart_RestoreSlewRate()
Definition lx200fs2.cpp:244
enum LX200FS2::TelescopeParkedStatus ParkedStatus
@ PARKED_STOPPED
Definition lx200fs2.h:74
@ UNPARKED_NEEDSLEW
Definition lx200fs2.h:75
@ PARKED_NEEDSTOP
Definition lx200fs2.h:73
@ PARKED_NOTPARKED
Definition lx200fs2.h:71
@ PARKED_NEEDABORT
Definition lx200fs2.h:72
INumberVectorProperty SlewAccuracyNP
Definition lx200fs2.h:63
void TrackingStart()
Definition lx200fs2.cpp:235
void TrackingStop_Abort()
Definition lx200fs2.cpp:219
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition lx200fs2.cpp:56
INumber SlewAccuracyN[2]
Definition lx200fs2.h:62
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
Definition lx200fs2.cpp:360
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition lx200fs2.cpp:38
virtual bool Park() override
Park the telescope to its home position.
Definition lx200fs2.cpp:178
virtual bool checkConnection() override
Definition lx200fs2.cpp:163
void TrackingStop()
Definition lx200fs2.cpp:208
virtual bool ReadScopeStatus() override
Read telescope status.
Definition lx200fs2.cpp:253
ISwitchVectorProperty StopAfterParkSP
Definition lx200fs2.h:65
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
Definition lx200fs2.cpp:371
virtual bool UnPark() override
Unpark the telescope if already parked.
Definition lx200fs2.cpp:312
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition lx200fs2.cpp:120
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition lx200fs2.cpp:98
virtual const char * getDefaultName() override
Definition lx200fs2.cpp:151
virtual bool isSlewComplete() override
Definition lx200fs2.cpp:156
virtual bool Goto(double r, double d) override
Move the scope to the supplied RA and DEC coordinates.
Definition lx200fs2.cpp:379
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition lx200fs2.cpp:168
virtual bool Sync(double r, double d) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
Definition lx200fs2.cpp:416
void TrackingStop_AllStop()
Definition lx200fs2.cpp:227
ISwitch StopAfterParkS[2]
Definition lx200fs2.h:66
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual void slewError(int slewCode)
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.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
INDI::PropertyNumber EqNP
INDI::PropertySwitch SlewRateSP
INDI::PropertyNumber LocationNP
double ra
double dec
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition indiapi.h:498
@ IP_RW
Definition indiapi.h:184
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_ATMOST1
Definition indiapi.h:172
@ DIRECTION_EAST
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:130
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:33
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:490
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition indidevapi.c:337
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition indidevapi.c:23
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:376
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:398
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:453
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:355
#define INDI_UNUSED(x)
Definition indidevapi.h:132
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define LOG_INFO(txt)
Definition indilogger.h:74
#define DEBUGF(priority, msg,...)
Definition indilogger.h:57
#define getDeviceName
int setObjectRA(int fd, double ra, bool addSpace)
int setObjectDEC(int fd, double dec, bool addSpace)
int Slew(int fd)
void EquatorialToHorizontal(IEquatorialCoordinates *object, IGeographicCoordinates *observer, double JD, IHorizontalCoordinates *position)
EquatorialToHorizontal Calculate horizontal coordinates from equatorial coordinates.
Definition libastro.cpp:141
void HorizontalToEquatorial(IHorizontalCoordinates *object, IGeographicCoordinates *observer, double JD, IEquatorialCoordinates *position)
HorizontalToEquatorial Calculate Equatorial EOD Coordinates from horizontal coordinates.
Definition libastro.cpp:161
char name[MAXINDINAME]
Definition indiapi.h:321
char name[MAXINDINAME]
Definition indiapi.h:369