38 #include <libnova/libnova.h>
40 #define PRODUCT_TAB "Product"
41 #define ALIGNMENT_TAB "Alignment"
42 #define LX200_TIMEOUT 5
45 #define REFRACTION_MODEL_TEMPERATURE "REFRACTION_MODEL_TEMPERATURE"
46 #define REFRACTION_MODEL_PRESSURE "REFRACTION_MODEL_PRESSURE"
47 #define MODEL_COUNT "MODEL_COUNT"
48 #define ALIGNMENT_POINTS "ALIGNMENT_POINTS"
49 #define ALIGNMENT_STATE "Alignment"
50 #define MINIMAL_NEW_ALIGNMENT_POINT_RO "MINIMAL_NEW_ALIGNMENT_POINT_RO"
51 #define MINIMAL_NEW_ALIGNMENT_POINT "MINIMAL_NEW_ALIGNMENT_POINT"
52 #define NEW_ALIGNMENT_POINT "NEW_ALIGNMENT_POINT"
53 #define NEW_ALIGNMENT_POINTS "NEW_ALIGNMENT_POINTS"
54 #define NEW_MODEL_NAME "NEW_MODEL_NAME"
55 #define PRODUCT_INFO "PRODUCT_INFO"
56 #define TLE_TEXT "TLE_TEXT"
57 #define TLE_NUMBER "TLE_NUMBER"
58 #define TRAJECTORY_TIME "TRAJECTORY_TIME"
59 #define SAT_TRACKING_STAT "SAT_TRACKING_STAT"
60 #define UNATTENDED_FLIP "UNATTENDED_FLIP"
103 LOG_INFO(
"Setting Ultra Precision Mode.");
111 LOG_ERROR(
"Failed to set Ultra Precision Mode.");
228 LOGF_INFO(
"Unattended Flip from config and mount are %s",
233 LOGF_INFO(
"Read Unattended Flip %s from config while mount has %s, updating mount",
241 LOG_INFO(
"Did not find an Unattended Flip setting in the config file. Specify desired behaviour in Motion Control tab and save config in Options tab.");
280 LOG_WARN(
"Failed to get tracking frequency from device.");
288 char RefractionModelTemperature[80];
291 sscanf(RefractionModelTemperature,
"%f#", &rmtemp);
296 char RefractionModelPressure[80];
299 sscanf(RefractionModelPressure,
"%f#", &rmpres);
320 LOG_INFO(
"Unattended Flip is disabled.");
326 LOG_INFO(
"Unattended Flip is enabled.");
334 LOG_INFO(
"sendLocationOnStartup is enabled, call sendScopeLocation.");
339 LOG_INFO(
"sendLocationOnStartup is disabled, do not call sendScopeLocation.");
343 LOG_INFO(
"sendTimeOnStartup is enabled, call sendScopeTime.");
348 LOG_INFO(
"sendTimeOnStartup is disabled, do not call sendScopeTime.");
353 bool LX200_10MICRON::getMountInfo()
355 char ProductName[80];
359 char FirmwareVersion[80];
361 char FirmwareDate1[80];
363 char FirmwareDate2[80];
366 sscanf(FirmwareDate1,
"%s %02d %04d", mon, &dd, &yyyy);
368 char FirmwareDate[80];
369 snprintf(FirmwareDate, 80,
"%04d-%02d-%02dT%s", yyyy,
monthToNumber(mon), dd, FirmwareDate2);
371 LOGF_INFO(
"Product:%s Control box:%s Firmware:%s of %s", ProductName, ControlBox, FirmwareVersion, FirmwareDate);
421 char cmd[] =
"#:Ginfo#";
425 int nbytes_write = 0, nbytes_read = 0;
432 tcflush(fd, TCIFLUSH);
437 term = strchr(data,
'#');
450 nbytes_read = sscanf(data,
"%g,%g,%c,%g,%g,%g,%d,%d#", &Ginfo.RA_JNOW, &Ginfo.DEC_JNOW, &Ginfo.SideOfPier,
451 &Ginfo.AZ, &Ginfo.ALT, &Ginfo.Jdate, &Ginfo.Gstat, &Ginfo.SlewStatus);
457 if (Ginfo.Gstat != OldGstat)
461 LOGF_INFO(
"Gstat changed from %d to %d", OldGstat, Ginfo.Gstat);
465 LOGF_INFO(
"Gstat initialized at %d", Ginfo.Gstat);
519 OldGstat = Ginfo.Gstat;
520 NewRaDec(Ginfo.RA_JNOW, Ginfo.DEC_JNOW);
523 char LocalSiderealTimeS[80];
525 f_scansexa(LocalSiderealTimeS, &Ginfo.SiderealTime);
595 return '1' == guaf[0];
607 snprintf(data,
sizeof(data),
"#:Suaf%d#", (setting ==
false) ? 0 : 1);
610 if (setting ==
false)
635 snprintf(data,
sizeof(data),
"#:FLIP#");
670 snprintf(data,
sizeof(data),
":SC%04d-%02d-%02d#", years, months, days);
692 LOGF_INFO(
"The function is called with TLE %s", tle);
693 if (strlen(tle) > 230)
699 std::string sep =
"$0a";
700 std::string search =
"\n";
701 tle_str = (std::string) tle;
702 for(
size_t pos = 0; ; pos += sep.length() )
705 pos = tle_str.find( search, pos );
706 if( pos == std::string::npos )
break;
708 tle_str.erase( pos, search.length() );
709 tle_str.insert( pos, sep );
712 snprintf(command,
sizeof(command),
":TLEL0%s#", tle_str.c_str());
723 if (response[0] ==
'E')
725 LOG_ERROR(
"Invalid formatting of TLE, trying to split:");
726 char *pch = strtok ((
char*) tle,
"\n");
727 while (pch !=
nullptr)
730 pch = strtok (
nullptr,
"\n");
737 char *pch = strtok ((
char*) tle,
"\n");
738 while (pch !=
nullptr)
741 pch = strtok (
nullptr,
"\n");
758 snprintf(command,
sizeof(command),
":TLEDL%d#", tleN);
760 LOG_INFO(
"Setting TLE from Database");
770 if (response[0] ==
'E')
792 struct ln_date start_pass;
793 if (
extractISOTime(start_pass_isodatetime.c_str(), &start_pass) == -1)
795 LOGF_ERROR(
"Date/Time is invalid: %s.", start_pass_isodatetime.c_str());
799 struct ln_date end_pass;
800 if (
extractISOTime(end_pass_isodatetime.c_str(), &end_pass) == -1)
802 LOGF_ERROR(
"Date/Time is invalid: %s.", end_pass_isodatetime.c_str());
808 JD_start = ln_get_julian_day(&start_pass);
809 JD_end = ln_get_julian_day(&end_pass);
810 int nextPassInMinutes =
static_cast<int>(ceil((JD_end - JD_start) * 24 * 60));
811 int nextPassinMinutesUpTo1440 =
std::min(nextPassInMinutes, 1440);
812 int nextPassinMinutesBetween1and1440 =
std::max(nextPassinMinutesUpTo1440, 1);
815 snprintf(command,
sizeof(command),
":TLEP%7.8f,%01d#", JD_start, nextPassinMinutesBetween1and1440);
817 LOGF_INFO(
"For the next %01d minutes", nextPassinMinutesBetween1and1440);
828 if (response[0] ==
'E')
830 LOG_ERROR(
"TLE not loaded or invalid command");
833 if (response[0] ==
'N')
854 snprintf(command,
sizeof(command),
":TLES#");
864 if (response[0] ==
'E')
869 if (response[0] ==
'F')
874 if (response[0] ==
'V')
876 LOG_INFO(
"Slewing to start of transit");
879 if (response[0] ==
'S')
881 LOG_INFO(
"Slewing to transiting satellite");
884 if (response[0] ==
'Q')
902 snprintf(data, 16,
"#:SRTMP%0+6.1f#", temperature);
916 snprintf(data, 16,
"#:SRPRS%06.1f#", pressure);
939 char MRa_str[32], MDec_str[32];
940 fs_sexa(MRa_str, MRa, 0, 36000);
941 fs_sexa(MDec_str, MDec, 0, 3600);
944 (
static_cast<int>(MSide) == 0) ? MSide_char =
'E' : MSide_char =
'W';
946 char PRa_str[32], PDec_str[32];
947 fs_sexa(PRa_str, PRa, 0, 36000);
948 fs_sexa(PDec_str, PDec, 0, 3600);
950 char SidTime_str[32];
951 fs_sexa(SidTime_str, SidTime, 0, 36000);
954 snprintf(command, 80,
"#:newalpt%s,%s,%c,%s,%s,%s#", MRa_str, MDec_str, MSide_char, PRa_str, PDec_str, SidTime_str);
965 int nbytes_read = sscanf(response,
"%3d#", &points);
968 LOGF_ERROR(
"AddSyncPoint response error %d", nbytes_read);
971 LOGF_INFO(
"AddSyncPoint responded [%4s], there are now %d new alignment points", response, points);
980 double MSide = (toupper(Ginfo.SideOfPier) ==
'E') ? 0 : 1;
981 return AddSyncPoint(Ginfo.RA_JNOW, Ginfo.DEC_JNOW, MSide, PRa, PDec, Ginfo.SiderealTime);
993 LOG_ERROR(
"SetRefractionModelTemperature error");
1008 LOG_ERROR(
"SetRefractionModelPressure error");
1037 LOG_ERROR(
"Cannot add alignment points yet, need to start a new alignment first");
1057 LOG_ERROR(
"Cannot add alignment points yet, need to start a new alignment first");
1082 if (strcmp(name,
"TLE_NUMBER") == 0)
1084 LOG_INFO(
"I am trying to set from Database");
1120 LOG_INFO(
"Alignment state is IDLE");
1167 LOG_ERROR(
"Delete current alignment error");
1172 LOG_INFO(
"Current Alignment deleted");
1235 LOG_ERROR(
"Setting unattended flip failed");
1240 LOG_INFO(
"Unattended flip disabled");
1245 LOG_ERROR(
"Setting unattended flip failed");
1250 LOG_INFO(
"Unattended flip enabled");
1278 if (strcmp(name,
"SAT_TLE_TEXT") == 0)
1297 LOG_ERROR(
"TLE was not correctly uploaded");
1301 if (strcmp(name,
"SAT_PASS_WINDOW") == 0)
1315 LOG_ERROR(
"Trajectory could not be calculated");
1331 entry month_table[] = { {
"Jan", 1 }, {
"Feb", 2 }, {
"Mar", 3 }, {
"Apr", 4 }, {
"May", 5 },
1332 {
"Jun", 6 }, {
"Jul", 7 }, {
"Aug", 8 }, {
"Sep", 9 }, {
"Oct", 10 },
1333 {
"Nov", 11 }, {
"Dec", 12 }, {
nullptr, 0 }
1335 entry *p = month_table;
1336 while (p->name !=
nullptr)
1338 if (strcasecmp(p->name, monthName) == 0)
1348 int nbytes_write = 0;
1351 tcflush(
fd, TCIFLUSH);
1354 LOGF_ERROR(
"CMD <%s> write ERROR %d", data, error_type);
1357 tcflush(
fd, TCIFLUSH);
1363 char bool_return[2];
1365 int nbytes_write = 0, nbytes_read = 0;
1368 tcflush(
fd, TCIFLUSH);
1371 LOGF_ERROR(
"CMD <%s> write ERROR %d", data, error_type);
1375 tcflush(
fd, TCIFLUSH);
1377 if (nbytes_read < 1)
1379 LOGF_ERROR(
"CMD <%s> read ERROR %d", data, error_type);
1383 if (bool_return[0] != expect[0])
1397 int nbytes_write = 0, nbytes_read = 0;
1400 tcflush(
fd, TCIFLUSH);
1403 LOGF_ERROR(
"CMD <%s> write ERROR %d", data, error_type);
1407 tcflush(
fd, TCIFLUSH);
1409 if (nbytes_read < 1)
1411 LOGF_ERROR(
"CMD <%s> read ERROR %d", data, error_type);
const char * getDeviceName() 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
TelescopeStatus TrackState
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
@ SAT_PASS_WINDOW_END
Index for end of the window.
@ SAT_PASS_WINDOW_START
Index for start of the window.
ITextVectorProperty SatPassWindowTP
Text Vector property defining the start and end of a satellite pass (window contains pass)....
bool isParked()
isParked is mount currently parked?
@ SAT_HALT
Halt signal (abort)
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
@ TELESCOPE_HAS_TRACK_RATE
@ TELESCOPE_HAS_PIER_SIDE
@ TELESCOPE_CAN_TRACK_SATELLITE
@ TELESCOPE_HAS_TRACK_MODE
@ TELESCOPE_CAN_CONTROL_TRACK
ISwitchVectorProperty TrackSatSP
Switch Vector property defining the state of the satellite tracking of the mount. Example implementat...
ISwitchVectorProperty ParkSP
IText SatPassWindowT[SAT_PASS_WINDOW_COUNT]
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
void setPierSide(TelescopePierSide side)
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
ITextVectorProperty TLEtoTrackTP
Text Vector property defining the orbital elements of an artificial satellite (TLE)....
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool sendScopeLocation()
bool sendLocationOnStartup
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.
INumberVectorProperty TrackFreqNP
@ LX200_HAS_PULSE_GUIDING
@ LX200_HAS_TRACKING_FREQ
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool sendScopeTime()
void setLX200Capability(uint32_t cap)
INumber RefractionModelTemperatureN[1]
void getBasicData() override
bool Handshake() override
perform handshake with device to check communication
bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
INumberVectorProperty ModelCountNP
INumberVectorProperty NewAlignmentPointsNP
ISwitchVectorProperty AlignmentStateSP
ITextVectorProperty NewModelNameTP
bool CalculateSatTrajectory(std::string start_pass_isodatetime, std::string end_pass_isodatetime)
INumberVectorProperty NewAlpNP
INumber NewAlignmentPointsN[1]
int setStandardProcedureAndExpectChar(int fd, const char *data, const char *expect)
@ UNATTENDED_FLIP_DISABLED
@ UNATTENDED_FLIP_ENABLED
bool UnPark() override
Unpark the telescope if already parked.
int monthToNumber(const char *monthName)
INumberVectorProperty RefractionModelPressureNP
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
int setStandardProcedureWithoutRead(int fd, const char *data)
INumberVectorProperty RefractionModelTemperatureNP
bool SetTLEtoFollow(const char *tle)
bool getUnattendedFlipSetting()
ITextVectorProperty ProductTP
bool setLocalDate(uint8_t days, uint8_t months, uint16_t years) override
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
const char * getDefaultName() override
virtual int SetRefractionModelPressure(double pressure)
INumber MiniNewAlpN[MALP_COUNT]
bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
INumberVectorProperty TLEfromDatabaseNP
INumber NewAlpN[ALP_COUNT]
int setStandardProcedureAndReturnResponse(int fd, const char *data, char *response, int max_response_length)
@ GSTAT_SLEWING_OR_STOPPING
@ GSTAT_TRACKING_OUTSIDE_LIMITS
@ GSTAT_FOLLOWING_SATELLITE
@ GSTAT_NOT_TRACKING_AND_NOT_MOVING
bool ReadScopeStatus() override
Read telescope status.
ISwitch UnattendedFlipS[UNATTENDED_FLIP_COUNT]
bool initProperties() override
Called to initialize basic properties required all the time.
INumber MiniNewAlpRON[MALPRO_COUNT]
bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual int SetRefractionModelTemperature(double temperature)
bool Park() override
Park the telescope to its home position.
bool SyncConfigBehaviour(bool cmcfg)
@ PRODUCT_FIRMWARE_VERSION
INumberVectorProperty MiniNewAlpRONP
ISwitchVectorProperty UnattendedFlipSP
INumber TLEfromDatabaseN[1]
INumber AlignmentPointsN[1]
int AddSyncPoint(double MRa, double MDec, double MSide, double PRa, double PDec, double SidTime)
INumberVectorProperty MiniNewAlpNP
ISwitch AlignmentStateS[ALIGN_COUNT]
INumberVectorProperty AlignmentPointsNP
bool SetTLEfromDatabase(int tleN)
int AddSyncPointHere(double PRa, double PDec)
bool setUnattendedFlipSetting(bool setting)
INumber RefractionModelPressureN[1]
const char * SATELLITE_TAB
SATELLITE_TAB.
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double. x can be anything non-numeric. Any missing A,...
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
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[].
Implementations for common driver routines.
int extractISOTime(const char *timestr, struct ln_date *iso_date)
Extract ISO 8601 time and store it in a tm struct.
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 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 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.
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 IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
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,...)
int IUGetConfigSwitch(const char *dev, const char *property, const char *member, ISState *value)
IUGetConfigSwitch Opens configuration file and reads single switch property.
#define LOGF_INFO(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
#define DEBUGFDEVICE(device, priority, msg,...)
#define NEW_ALIGNMENT_POINT
#define MINIMAL_NEW_ALIGNMENT_POINT
#define REFRACTION_MODEL_PRESSURE
#define NEW_ALIGNMENT_POINTS
#define MINIMAL_NEW_ALIGNMENT_POINT_RO
#define REFRACTION_MODEL_TEMPERATURE
int getCommandInt(int fd, int *value, const char *cmd)
int setStandardProcedure(int fd, const char *data)
int checkLX200EquatorialFormat(int fd)
int setCommandInt(int fd, int data, const char *cmd)
int getTrackFreq(int fd, double *value)
int getCommandString(int fd, char *data, const char *cmd)