31 #include <libnova/sidereal_time.h>
46 #define SIDRATE 0.004178
48 #define FIRMWARE_TAB "Firmware data"
50 #define ONSTEP_TIMEOUT 3
53 static std::unique_ptr<LX200_TeenAstro> teenAstro(
new LX200_TeenAstro());
70 LOG_DEBUG(
"Initializing from LX200 TeenAstro device...");
86 return "LX200 TeenAstro";
104 IUFillText(&ErrorStatusT[0],
"Error code",
"",
"");
128 IUFillNumber(&SlewAccuracyN[0],
"SlewRA",
"RA (arcmin)",
"%10.6m", 0., 60., 1., 3.0);
129 IUFillNumber(&SlewAccuracyN[1],
"SlewDEC",
"Dec (arcmin)",
"%10.6m", 0., 60., 1., 3.0);
138 IUFillSwitchVector(&SiteSP, SiteS, 4,
getDeviceName(),
"Sites",
"",
SITE_TAB,
IP_RW,
ISR_1OFMANY, 0,
IPS_IDLE);
235 LOG_ERROR(
"Error communicating with telescope.");
265 if (isSlewComplete())
268 LOG_INFO(
"Slew is complete. Tracking...");
278 if (OSStat[15] !=
'0')
280 updateMountStatus(OSStat[15]);
282 if (strcmp(OSStat, OldOSStat) != 0)
284 handleStatusChange();
285 snprintf(OldOSStat,
sizeof(OldOSStat),
"%s", OSStat);
292 currentRA += 0.000001;
310 void LX200_TeenAstro::handleStatusChange(
void)
314 if (OSStat[0] != OldOSStat[0])
316 if (OSStat[0] ==
'0')
320 else if (OSStat[0] ==
'1')
324 else if (OSStat[0] ==
'2' || OSStat[0] ==
'3' )
332 if (OSStat[2] != OldOSStat[2])
334 if (OSStat[2] ==
'P')
345 if (OSStat[4] != OldOSStat[4])
352 if (OSStat[13] != OldOSStat[13])
357 if (OSStat[15] != OldOSStat[15])
359 updateMountStatus(OSStat[15]);
368 void LX200_TeenAstro::updateMountStatus(
char status)
370 static const char *errCodes[9] = {
"ERR_NONE",
"ERR_MOTOR_FAULT",
"ERR_ALT",
"ERR_LIMIT_SENSE",
371 "ERR_AXIS2",
"ERR_AZM",
"ERR_UNDER_POLE",
"ERR_MERIDIAN",
"ERR_SYNC"
374 if (status < '0' || status >
'9')
387 IUSaveText(&ErrorStatusT[0], errCodes[status -
'0']);
400 char RAStr[64] = {0}, DecStr[64] = {0};
402 fs_sexa(RAStr, targetRA, 2, 3600);
403 fs_sexa(DecStr, targetDEC, 2, 3600);
421 const struct timespec ms100_delay = {.tv_sec = 0, .tv_nsec = 100000000};
422 nanosleep(&ms100_delay, NULL);
440 IDSetNumber(&
EqNP,
"Error Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
449 LOGF_INFO(
"Slewing to RA: %s - DEC: %s", RAStr, DecStr);
453 bool LX200_TeenAstro::isSlewComplete()
457 return fabs(dx) <= (SlewAccuracyN[0].value / (900.0)) && fabs(dy) <= (SlewAccuracyN[1].value / 60.0);
475 char syncString[256] = {0};
496 LOG_INFO(
"Synchronization successful.");
518 LOGF_WARN(
"===CMD==> Set Park Pos %s", response);
523 LOG_WARN(
"Park Value set to current position");
563 IDSetSwitch(&(Telescope::AbortSP),
"Abort slew failed.");
566 Telescope::AbortSP.s =
IPS_OK;
568 IDSetSwitch(&(Telescope::AbortSP),
"Slew aborted.");
591 LOG_INFO(
"Parking is in progress...");
609 void LX200_TeenAstro::updateSlewRate()
614 if (getSlewRate(&slewRateIndex))
616 LOGF_INFO(
"current slew rate : %d", slewRateIndex);
618 SlewRateS[slewRateIndex].s =
ISS_ON;
624 LOG_ERROR(
"Error reading current slew rate");
634 int currentSiteIndex;
645 statusCommand =
":GXI#";
646 guideSpeedCommand =
":SXR0:%02d#";
652 SiteNameT[0].text =
new char[64];
655 if (getSiteIndex(¤tSiteIndex))
657 SiteS[currentSiteIndex].s =
ISS_ON;
658 currentSiteNum = currentSiteIndex + 1;
659 LOGF_INFO(
"Site number %d", currentSiteNum);
669 LOG_ERROR(
"Error reading current site number");
674 for (
unsigned i = 0; i <
sizeof(OldOSStat); i++)
677 handleStatusChange();
693 LOG_INFO(
"=============== Parkdata loaded");
698 LOG_INFO(
"=============== Parkdata Load Failed");
713 if (!strcmp(name, SlewAccuracyNP.
name))
720 if (SlewAccuracyN[0].value < 3 || SlewAccuracyN[1].value < 3)
721 IDSetNumber(&SlewAccuracyNP,
"Warning: Setting the slew accuracy too low may result in a dead lock");
726 if (!strcmp(name, GuideRateNP.
name))
731 float guideRate = GuideRateN[0].value;
732 SetGuideRate(guideRate);
756 if (!strcmp(name, SlewRateSP.
name))
761 if (!selectSlewRate(slewRate))
763 LOGF_ERROR(
"Error setting move to rate %d.", slewRate);
773 if (!strcmp(name, SiteSP.
name))
779 LOGF_DEBUG(
"currentSiteNum: %d", currentSiteNum);
798 LOGF_INFO(
"Setting site number %d", currentSiteNum);
799 SiteS[currentSiteNum - 1].s =
ISS_ON;
817 if (!strcmp(name, SiteNameTP.
name))
842 bool LX200_TeenAstro::getLocalDate(
char *dateString)
846 time_t now = time(
nullptr);
847 strftime(dateString,
MAXINDINAME,
"%F", localtime(&now));
857 bool LX200_TeenAstro::setLocalDate(uint8_t days, uint8_t months, uint16_t years)
862 bool LX200_TeenAstro::getLocalTime(
char *timeString)
866 time_t now = time(
nullptr);
867 strftime(timeString,
MAXINDINAME,
"%T", localtime(&now));
875 snprintf(timeString,
MAXINDINAME,
"%02d:%02d:%02d", h, m, s);
882 bool LX200_TeenAstro::getUTFOffset(
double *offset)
890 int lx200_utc_offset = 0;
894 *offset = lx200_utc_offset * -1;
898 bool LX200_TeenAstro::sendScopeTime()
906 memset(<m, 0,
sizeof(ltm));
907 memset(&utm, 0,
sizeof(utm));
911 if (getUTFOffset(&offset))
913 char utcStr[8] = {0};
914 snprintf(utcStr,
sizeof(utcStr),
"%.2f", offset);
919 LOG_WARN(
"Could not obtain UTC offset from mount!");
923 if (getLocalTime(ctime) ==
false)
925 LOG_WARN(
"Could not obtain local time from mount!");
929 if (getLocalDate(cdate) ==
false)
931 LOG_WARN(
"Could not obtain local date from mount!");
937 snprintf(datetime,
MAXINDINAME,
"%sT%s", cdate, ctime);
940 if (strptime(datetime,
"%FT%T", <m) ==
nullptr)
942 LOGF_WARN(
"Could not process mount date and time: %s", datetime);
948 time_epoch = mktime(<m);
951 time_epoch -=
static_cast<int>(offset * 3600.0);
954 localtime_r(&time_epoch, &utm);
957 strftime(cdate,
MAXINDINAME,
"%Y-%m-%dT%H:%M:%S", &utm);
973 bool LX200_TeenAstro::sendScopeLocation()
975 int dd = 0, mm = 0, elev = 0;
993 LOG_WARN(
"Failed to get site latitude from device.");
1005 LOG_WARN(
"Failed to get site longitude from device.");
1018 if (getSiteElevation(&elev))
1024 LOG_ERROR(
"Error getting site elevation");
1035 bool LX200_TeenAstro::getSiteElevation(
int *elevationP)
1045 bool LX200_TeenAstro::getSiteIndex(
int *ndxP)
1056 bool LX200_TeenAstro::getSlewRate(
int *ndxP)
1058 unsigned char rate = (OSStat[4] -
'0');
1068 bool LX200_TeenAstro::setSite(
int num)
1071 snprintf (buf,
sizeof(buf),
":W%d#", num - 1);
1079 bool LX200_TeenAstro::setSiteElevation(
double elevation)
1082 snprintf (buf,
sizeof(buf),
":Se%+4d#",
static_cast<int>(elevation));
1092 bool LX200_TeenAstro::getLocation()
1094 int dd = 0, mm = 0, elev = 0;
1099 LOG_WARN(
"Failed to get site latitude from device.");
1112 LOG_WARN(
"Failed to get site longitude from device.");
1122 if (getSiteElevation(&elev))
1128 LOG_ERROR(
"Error getting site elevation");
1138 bool LX200_TeenAstro::SetGuideRate(
float guideRate)
1142 snprintf (cmdString,
sizeof(cmdString), guideSpeedCommand, (
int) (guideRate * 100));
1143 sendCommand(cmdString);
1176 void LX200_TeenAstro::SendPulseCmd(int8_t direction, uint32_t duration_msec)
1222 bool LX200_TeenAstro::Move(
TDirection dir, TelescopeMotionCommand
cmd)
1251 void LX200_TeenAstro::mountSim()
1253 static struct timeval ltv;
1259 gettimeofday(&tv,
nullptr);
1261 if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
1264 dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
1317 void LX200_TeenAstro::slewError(
int slewCode)
1323 else if (slewCode == 2)
1337 sendCommand(
":Te#");
1341 sendCommand(
":Td#");
1349 bool LX200_TeenAstro::selectSlewRate(
int index)
1353 snprintf(
cmd,
sizeof(
cmd),
":R%d#", index);
1363 void LX200_TeenAstro::sendCommand(
const char *
cmd)
const char * getDeviceName() const
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
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 addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
uint16_t getDriverInterface() const
INumberVectorProperty GuideNSNP
void initGuiderProperties(const char *deviceName, const char *groupName)
Initilize guider properties. It is recommended to call this function within initProperties() of your ...
INumberVectorProperty GuideWENP
void processGuiderProperties(const char *name, double values[], char *names[], int n)
Call this function whenever client updates GuideNSNP or GuideWSP properties in the primary device....
TelescopeStatus TrackState
ISwitchVectorProperty ParkOptionSP
void SetAxis1Park(double value)
SetRAPark Set current RA/AZ parking position. The data park file (stored in ~/.indi/ParkData....
ISwitchVectorProperty MovementNSSP
ISwitchVectorProperty AbortSP
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
INumberVectorProperty LocationNP
virtual bool initProperties() override
Called to initialize basic properties required all the time.
ITextVectorProperty TimeTP
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
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...
virtual int AddTrackMode(const char *name, const char *label, bool isDefault=false)
AddTrackMode.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
INumberVectorProperty EqNP
@ TELESCOPE_HAS_PIER_SIDE
@ TELESCOPE_HAS_TRACK_MODE
@ TELESCOPE_CAN_CONTROL_TRACK
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
ISwitchVectorProperty ParkSP
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
void setPierSide(TelescopePierSide side)
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
ISwitchVectorProperty MovementWESP
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....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
void SetParkDataType(TelescopeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
virtual const char * getDriverName() override
virtual bool Goto(double, double) override
Move the scope to the supplied RA and DEC coordinates.
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
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...
virtual bool Handshake() override
perform handshake with device to check communication
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
virtual const char * getDefaultName() override
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool Park() override
Park the telescope to its home position.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void getBasicData()
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
const char * GUIDE_TAB
GUIDE_TAB Where all the properties for guiding are located.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
const char * SITE_TAB
SITE_TAB Where all site information setting are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
void getSexComponents(double value, int *d, int *m, int *s)
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
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[].
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
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.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
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.
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
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.
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.
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
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.
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
std::mutex lx200CommsLock
#define INITIAL_GUIDE_RATE
int SendPulseCmd(int fd, int direction, int duration_msec, bool wait_after_command, int max_wait_ms)
int getSiteLongitude(int fd, int *ddd, int *mm, double *ssf)
int selectTrackingMode(int fd, int trackMode)
int getSiteName(int fd, char *siteName, int siteNum)
int getCommandInt(int fd, int *value, const char *cmd)
int setObjectRA(int fd, double ra, bool addSpace)
int setObjectDEC(int fd, double dec, bool addSpace)
int checkLX200EquatorialFormat(int fd)
int setCalenderDate(int fd, int dd, int mm, int yy, bool addSpace)
int getCalendarDate(int fd, char *date)
int MoveTo(int fd, int direction)
int setSiteName(int fd, char *siteName, int siteNum)
void setLX200Debug(const char *deviceName, unsigned int debug_level)
int HaltMovement(int fd, int direction)
int getCommandString(int fd, char *data, const char *cmd)
int getSiteLatitude(int fd, int *dd, int *mm, double *ssf)
#define getUTCOffset(fd, x)
#define getVersionDate(fd, x)
#define getVersionTime(fd, x)
#define getLX200DEC(fd, x)
#define getVersionNumber(fd, x)
#define getLX200RA(fd, x)
#define getProductName(fd, x)
#define getLocalTime24(fd, x)
std::vector< uint8_t > buffer
bool setSite(const int fd, const double longitude, const double latitude)
static Logger & getInstance()
Method to get a reference to the object (i.e., Singleton) It is a static method.
int addDebugLevel(const char *debugLevelName, const char *LoggingLevelName)
Adds a new debugging level to the driver.