6#include <libnova/transform.h>
41 MountTypeSP[TYPE_AZIMUTH].
fill(
"Azimuth",
"Azimuth",
ISS_OFF);
42 MountTypeSP[TYPE_EQUATORIAL].
fill(
"Equatorial",
"Equatorial",
ISS_ON);
45 if (MountTypeSP[TYPE_EQUATORIAL].getState() ==
ISS_ON)
63 GuideRateNP[0].
fill(
"RATE",
"Rate",
"%.2f", 0.1, 0.9, 0.1, 0.5);
70 BuzzerSP[BUZZER_HIGH].
fill(
"HIGH",
"High",
ISS_ON);
76 BuzzerSP.setState(IPState::IPS_OK);
80 BuzzerSP.setState(IPState::IPS_ALERT);
89 MeridianFlipSP.
load();
92 MeridianTrackSP[MERIDIAN_TRACK].
fill(
"TRACK",
"Track",
ISS_ON);
93 MeridianTrackSP[MERIDIAN_STOP].
fill(
"STOP",
"Stop",
ISS_OFF);
96 MeridianTrackSP.
load();
99 MeridianLimitNP[0].
fill(
"LIMIT",
"LIMIT (deg)",
"%.f", -15, 15, 1, 0);
101 MeridianLimitNP.
load();
119 if (MountTypeSP[TYPE_EQUATORIAL].getState() ==
ISS_ON)
131 if (MountTypeSP[TYPE_EQUATORIAL].getState() ==
ISS_ON)
150 MountTypeSP.
update(states, names, n);
157 if (state ==
IPS_OK && previousType != targetType)
158 LOG_WARN(
"You must reconnect mount for change to take effect.");
169 MeridianFlipSP.
update(states, names, n);
171 MeridianTrackSP[MERIDIAN_TRACK].getState() ==
ISS_ON,
172 MeridianLimitNP[0].getValue());
174 MeridianFlipSP.
apply();
182 MeridianTrackSP.
update(states, names, n);
184 MeridianTrackSP[MERIDIAN_TRACK].getState() ==
ISS_ON,
185 MeridianLimitNP[0].getValue());
187 MeridianTrackSP.
apply();
203 GuideRateNP.
update(values, names, n);
212 MeridianLimitNP.
update(values, names, n);
214 MeridianTrackSP[MERIDIAN_TRACK].getState() ==
ISS_ON,
215 MeridianLimitNP[0].getValue());
217 MeridianLimitNP.
apply();
228 return "TOUPTEK SH20";
233 LOG_DEBUG(
"Checking SH20 connection...");
236 for (
int i = 0; i < 2; i++)
241 const struct timespec timeout = {0, 250000000L};
242 nanosleep(&timeout, NULL);
254 bool isNotMove =
true, isAtHome =
false;
256 char status[DRIVER_LEN] = {0};
257 if (sendCommand(
":GU#", status))
259 isNotMove = strchr(status,
'N');
260 isAtHome = strchr(status,
'H');
277 LOG_INFO(
"Slew is complete. Tracking...");
289 char response[DRIVER_LEN] = {0};
290 if (sendCommand(
":GTS#", response))
293 auto nowTracking = response[0] ==
'1';
294 if (wasTracking != nowTracking)
309 char response[DRIVER_LEN] = {0};
310 if (sendCommand(
":Gm#", response))
312 if (response[0] ==
'1')
314 else if (response[0] ==
'0')
332 int d = 0, m = 0, s = 0;
336 longitude = longitude - 360;
338 char command[DRIVER_LEN] = {0};
340 snprintf(command, DRIVER_LEN,
":Sg%c%03d*%02d:%02d#", longitude >= 0 ?
'+' :
'-', std::abs(d), m, s);
343 LOG_ERROR(
"Error setting site longitude coordinates");
348 snprintf(command, DRIVER_LEN,
":St%c%02d*%02d:%02d#", latitude >= 0 ?
'+' :
'-', std::abs(d), m, s);
351 LOG_ERROR(
"Error setting site latitude coordinates");
363 int h = 0, m = 0, s = 0;
364 char command[DRIVER_LEN] = {0};
367 snprintf(command, DRIVER_LEN,
":SG%c%02d:%02d#", offset >= 0 ?
'+' :
'-', std::abs(h), m);
373 char command[DRIVER_LEN] = {0};
374 snprintf(command, DRIVER_LEN,
":SC%02d/%02d/%02d#", months, days, years % 100);
383 const struct timespec timeout = {0, 100000000L};
387 char RAStr[64] = {0}, DecStr[64] = {0};
434 nanosleep(&timeout,
nullptr);
452 LOGF_ERROR(
"Error Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
461 LOGF_INFO(
"Slewing to RA: %s - DEC: %s", RAStr, DecStr);
471 char command[DRIVER_LEN] = {0};
472 snprintf(command, DRIVER_LEN,
":R%d#", index);
473 return sendCommand(command);
481 char response[DRIVER_LEN] = {0};
482 bool rc = sendCommand(enabled ?
":Te#" :
":Td#", response, 4, 1);
483 return rc && response[0] ==
'1';
491 char response[DRIVER_LEN] = {0};
492 bool rc = sendCommand(
":SPc#", response, 5, 1);
493 return rc && response[0] ==
'1';
498 if (!sendCommand(
":MP1#"))
506 if (!sendCommand(
":MP0#"))
541bool ToupSH20::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
543 int nbytes_written = 0, nbytes_read = 0, rc = -1;
545 tcflush(
PortFD, TCIOFLUSH);
549 char hex_cmd[DRIVER_LEN * 3] = {0};
550 hexDump(hex_cmd,
cmd, cmd_len);
564 LOGF_ERROR(
"Serial write error: %s.", errstr);
575 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
589 char hex_res[DRIVER_LEN * 3] = {0};
590 hexDump(hex_res, res, res_len);
598 tcflush(
PortFD, TCIOFLUSH);
603void ToupSH20::hexDump(
char * buf,
const char * data,
int size)
605 for (
int i = 0; i < size; i++)
606 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
609 buf[3 * size - 1] =
'\0';
615void ToupSH20::getStartupData()
622 if (MountTypeSP[TYPE_EQUATORIAL].getState() ==
ISS_ON)
623 getMeridianFlipSettings();
629bool ToupSH20::setMountType(
int type)
631 return sendCommand((
type == TYPE_EQUATORIAL) ?
":AP#" :
":AA#");
634bool ToupSH20::getMountType()
636 char response[DRIVER_LEN] = {0};
637 if (sendCommand(
":GU#", response))
655bool ToupSH20::goHome()
657 return sendCommand(
":MH#");
660bool ToupSH20::findHome()
662 const char cmd[] =
":MFH#";
664 return sendCommand(
cmd, &status, strlen(
cmd),
sizeof(status)) && status ==
'1';
670bool ToupSH20::getTrackMode()
672 char response[DRIVER_LEN] = {0};
673 if (sendCommand(
":GT#", response))
676 auto onIndex = response[0];
689bool ToupSH20::setGuideRate(
double value)
691 char command[DRIVER_LEN] = {0};
692 snprintf(command, DRIVER_LEN,
":Sgr%.2f#", value);
693 return sendCommand(command);
696bool ToupSH20::getGuideRate()
698 char response[DRIVER_LEN] = {0};
699 if (sendCommand(
":Ggr#", response))
702 if (sscanf(response,
"%lf", &value) == 1)
704 GuideRateNP[0].setValue(value);
715bool ToupSH20::setBuzzer(
int value)
717 char command[DRIVER_LEN] = {0};
718 snprintf(command, DRIVER_LEN,
":SBz%d#", value);
719 return sendCommand(command);
722bool ToupSH20::getBuzzer()
724 char response[DRIVER_LEN] = {0};
725 if (sendCommand(
":GBz#", response))
728 auto onIndex = response[0];
743bool ToupSH20::setMeridianFlipSettings(
bool enabled,
bool track,
double limit)
745 char command[DRIVER_LEN] = {0};
746 snprintf(command, DRIVER_LEN,
":STa%d%d%c%02d#", enabled ? 1 : 0, track ? 1 : 0,
747 limit >= 0 ?
'+' :
'-', static_cast<int>(
std::abs(limit)));
748 char response[2] = {0};
749 auto rc = sendCommand(command, response, -1, 1);
750 return rc && response[0] ==
'1';
753bool ToupSH20::getMeridianFlipSettings()
755 char response[DRIVER_LEN] = {0};
756 if (sendCommand(
":GTa#", response))
758 if (strlen(response) >= 5)
760 MeridianFlipSP.
reset();
764 MeridianTrackSP.
reset();
765 MeridianTrackSP[response[1] ==
'1' ? MERIDIAN_TRACK : MERIDIAN_STOP].
setState(
ISS_ON);
768 char *sign = &response[2];
769 char *limit = &response[3];
770 int limitValue = atoi(limit);
772 limitValue = -limitValue;
773 MeridianLimitNP[0].setValue(limitValue);
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 setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool load()
load Attempt to load property values from configuration file.
void setLabel(const char *label)
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
int findOnSwitchIndex() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void onUpdate(const std::function< void()> &callback)
TelescopeStatus TrackState
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
@ TELESCOPE_CAN_HOME_FIND
@ TELESCOPE_HAS_PIER_SIDE
@ TELESCOPE_HAS_TRACK_MODE
@ TELESCOPE_CAN_CONTROL_TRACK
uint32_t GetTelescopeCapability() const
GetTelescopeCapability returns the capability of the Telescope.
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...
void SetParkDataType(TelescopeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
@ LX200_HAS_PULSE_GUIDING
virtual void slewError(int slewCode)
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
void setLX200Capability(uint32_t cap)
virtual bool ReadScopeStatus() override
Read telescope status.
virtual const char * getDefaultName() override
virtual bool Park() override
Park the telescope to its home position.
virtual bool checkConnection() override
virtual bool SetSlewRate(int index) override
Override - Slew rate.
virtual bool Goto(double ra, double dec) override
Override - Goto.
virtual bool SetCurrentPark() override
Override - Park.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Override - Location.
virtual bool setUTCOffset(double offset) override
Override - Date.
virtual bool setLocalDate(uint8_t days, uint8_t months, uint16_t years) override
virtual bool SetTrackEnabled(bool enabled) override
Override - Track enable.
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual IPState ExecuteHomeAction(TelescopeHomeAction action) override
Override - Home.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
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 * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
INDI::PropertySwitch AbortSP
INDI::PropertySwitch MovementNSSP
INDI::PropertyNumber EqNP
INDI::PropertySwitch TrackStateSP
INDI::PropertySwitch HomeSP
INDI::PropertySwitch SlewRateSP
INDI::PropertySwitch TrackModeSP
INDI::PropertySwitch MovementWESP
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
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 tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
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[].
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Implementations for common driver routines.
#define LOGF_INFO(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,...)
int setObjectRA(int fd, double ra, bool addSpace)
int getLX200EquatorialFormat()
int setStandardProcedure(int fd, const char *data)
int setObjectDEC(int fd, double dec, bool addSpace)
#define getLX200DEC(fd, x)
#define getLX200RA(fd, x)