27#include <libnova/transform.h>
72 MountTypeSP[Azimuth].
fill(
"Azimuth",
"Azimuth",
ISS_OFF);
73 MountTypeSP[Equatorial].
fill(
"Equatorial",
"Equatorial",
ISS_ON);
77 if (MountTypeSP[Equatorial].getState() ==
ISS_ON)
101 GuideRateNP[0].
fill(
"RATE",
"Rate",
"%.2f", 0.1, 0.9, 0.1, 0.5);
120 MeridianFlipSP.
load();
123 PostMeridianTrackSP[TRACK].
fill(
"TRACK",
"Track",
ISS_ON);
124 PostMeridianTrackSP[STOP].
fill(
"STOP",
"Stop",
ISS_OFF);
127 PostMeridianTrackSP.
load();
130 MeridianLimitNP[0].
fill(
"LIMIT",
"Limit (deg)",
"%.f", -15, 15, 1, 0);
132 MeridianLimitNP.
load();
137 AltitudeLimitSP.
fill(
getDeviceName(),
"ALTITUDE_LIMIT_CONTROL",
"Altitude Limit Control", ALTITUDE_LIMIT_TAB,
IP_RW,
140 AltitudeLimitUpperNP[0].
fill(
"UPPER_LIMIT",
"Upper Limit (deg)",
"%.f", 60, 90, 1, 90);
141 AltitudeLimitUpperNP.
fill(
getDeviceName(),
"ALTITUDE_UPPER_LIMIT",
"Altitude Upper Limit", ALTITUDE_LIMIT_TAB,
IP_RW, 60,
144 AltitudeLimitLowerNP[0].
fill(
"LOWER_LIMIT",
"Lower Limit (deg)",
"%.f", 0, 30, 1, 0);
145 AltitudeLimitLowerNP.
fill(
getDeviceName(),
"ALTITUDE_LOWER_LIMIT",
"Altitude Lower Limit", ALTITUDE_LIMIT_TAB,
IP_RW, 60,
149 MultiStarAlignSP[CLEAR_ALIGNMENT_DATA].
fill(
"CLEAR",
"Clear Data",
ISS_OFF);
154 VariableSlewRateNP[0].
fill(
"RATE",
"Rate (x Sidereal)",
"%.2f", 0.00, 1440.00, 0.01, 1440.00);
158 FirmwareTP[FIRMWARE_MODEL].
fill(
"MODEL",
"Model",
"");
159 FirmwareTP[FIRMWARE_VERSION].
fill(
"VERSION",
"Version",
"");
187 if (MountTypeSP[Equatorial].getState() ==
ISS_ON)
215 if (MountTypeSP[Equatorial].getState() ==
ISS_ON)
255 for (
int i = 0; i < 2; i++)
260 const struct timespec ms250_delay = {.tv_sec = 0, .tv_nsec = 250000000};
261 nanosleep(&ms250_delay, NULL);
270void LX200AM5::setup()
286 if (MountTypeSP[Equatorial].getState() ==
ISS_ON)
287 getMeridianFlipSettings();
290 getAltitudeLimitStatus();
291 getAltitudeLimitUpper();
292 getAltitudeLimitLower();
295 checkMountParkState();
310 return updateProperty(MountTypeSP, states, names, n, [
this, names]()
315 int newType = MountTypeSP[Azimuth].
isNameMatch(names[0]) ? Azimuth : Equatorial;
316 bool rc = setMountType(newType);
317 if (rc && previousType != newType)
318 LOG_WARN(
"You must restart mount for change to take effect.");
330 if (BuzzerSP[Off].isNameMatch(names[0]))
331 return setBuzzer(Off);
332 if (BuzzerSP[Low].isNameMatch(names[0]))
333 return setBuzzer(Low);
334 if (BuzzerSP[High].isNameMatch(names[0]))
335 return setBuzzer(High);
343 return updateProperty(HeavyDutyModeSP, states, names, n, [
this, names]()
345 return setHeavyDutyMode(HeavyDutyModeSP[
INDI_ENABLED].isNameMatch(names[0]));
352 return updateProperty(MeridianFlipSP, states, names, n, [
this, names]()
354 return setMeridianFlipSettings(MeridianFlipSP[
INDI_ENABLED].isNameMatch(names[0]),
355 PostMeridianTrackSP[TRACK].getState() ==
ISS_ON,
356 MeridianLimitNP[0].getValue());
363 return updateProperty(PostMeridianTrackSP, states, names, n, [
this, names]()
366 PostMeridianTrackSP[TRACK].isNameMatch(names[0]),
367 MeridianLimitNP[0].getValue());
374 CustomParkSP.
update(states, names, n);
381 return updateProperty(AltitudeLimitSP, states, names, n, [
this, names]()
383 return setAltitudeLimitEnabled(AltitudeLimitSP[
INDI_ENABLED].isNameMatch(names[0]));
390 MultiStarAlignSP.
update(states, names, n);
391 if (MultiStarAlignSP[CLEAR_ALIGNMENT_DATA].getState() ==
ISS_ON)
399 MultiStarAlignSP.
apply();
417 return updateProperty(GuideRateNP, values, names, n, [
this, values]()
419 return setGuideRate(values[0]);
426 return updateProperty(MeridianLimitNP, values, names, n, [
this, values]()
429 PostMeridianTrackSP[TRACK].getState() ==
ISS_ON,
437 return updateProperty(AltitudeLimitUpperNP, values, names, n, [
this, values]()
439 return setAltitudeLimitUpper(values[0]);
446 return updateProperty(AltitudeLimitLowerNP, values, names, n, [
this, values]()
448 return setAltitudeLimitLower(values[0]);
455 return updateProperty(VariableSlewRateNP, values, names, n, [
this, values]()
457 return setVariableSlewRate(values[0]);
468bool LX200AM5::setMountType(
int type)
470 return sendCommand((
type == Azimuth) ?
":AA#" :
":AP#");
476bool LX200AM5::getMountType()
478 char response[DRIVER_LEN] = {0};
479 if (sendCommand(
":GU#", response))
499 char command[DRIVER_LEN] = {0};
500 snprintf(command, DRIVER_LEN,
":R%d#", index);
501 return sendCommand(command);
509bool LX200AM5::setGuideRate(
double value)
511 char command[DRIVER_LEN] = {0};
512 snprintf(command, DRIVER_LEN,
":Rg%.2f#", value);
513 return sendCommand(command);
519bool LX200AM5::getGuideRate()
521 char response[DRIVER_LEN] = {0};
522 if (sendCommand(
":Ggr#", response))
525 int result = sscanf(response,
"%f", &rate);
528 GuideRateNP[0].setValue(rate);
541bool LX200AM5::getTrackMode()
543 char response[DRIVER_LEN] = {0};
544 if (sendCommand(
":GT#", response))
547 auto onIndex = response[0] - 0x30;
563bool LX200AM5::setBuzzer(
int value)
565 char command[DRIVER_LEN] = {0};
566 snprintf(command, DRIVER_LEN,
":SBu%d#", value);
567 return sendCommand(command);
573bool LX200AM5::getBuzzer()
575 char response[DRIVER_LEN] = {0};
576 if (sendCommand(
":GBu#", response))
579 auto onIndex = response[0] - 0x30;
580 if (onIndex >= 0 && onIndex <
static_cast<int>(BuzzerSP.
count()))
596bool LX200AM5::getHeavyDutyMode()
598 char response[DRIVER_LEN] = {0};
599 if (sendCommand(
":GRl#", response))
601 HeavyDutyModeSP.
reset();
603 if (strcmp(response,
"1440#") == 0)
608 if (strcmp(response,
"720#") == 0)
626bool LX200AM5::setHeavyDutyMode(
bool enable)
629 char response[DRIVER_LEN] = {0};
630 return sendCommand(enable ?
":SRl720#" :
":SRl1440#", response, -1, 1) && response[0] ==
'1';
636bool LX200AM5::setMeridianFlipSettings(
bool enabled,
bool track,
double limit)
638 char command[DRIVER_LEN] = {0};
639 snprintf(command, DRIVER_LEN,
":STa%d%d%c%02d#", enabled ? 1 : 0, track ? 1 : 0,
640 limit >= 0 ?
'+' :
'-', static_cast<int>(
std::abs(limit)));
641 char response[2] = {0};
642 auto rc = sendCommand(command, response, -1, 1);
643 return rc && response[0] ==
'1';
649bool LX200AM5::getMeridianFlipSettings()
651 char response[DRIVER_LEN] = {0};
652 if (sendCommand(
":GTa#", response))
654 if (strlen(response) >= 5)
657 MeridianFlipSP.
reset();
662 PostMeridianTrackSP.
reset();
663 PostMeridianTrackSP[response[1] ==
'1' ? TRACK : STOP].
setState(
ISS_ON);
667 char *sign = &response[2];
668 char *limit = &response[3];
669 int limitValue = atoi(limit);
671 limitValue = -limitValue;
672 MeridianLimitNP[0].setValue(limitValue);
688bool LX200AM5::setAltitudeLimitEnabled(
bool enable)
691 char response[DRIVER_LEN] = {0};
692 return sendCommand(enable ?
":SLE#" :
":SLD#", response, -1, 1) && response[0] ==
'1';
698bool LX200AM5::getAltitudeLimitStatus()
700 char response[DRIVER_LEN] = {0};
701 if (sendCommand(
":GLC#", response))
703 AltitudeLimitSP.
reset();
715bool LX200AM5::setAltitudeLimitUpper(
double limit)
717 char command[DRIVER_LEN] = {0};
718 snprintf(command, DRIVER_LEN,
":SLH%02d#",
static_cast<int>(limit));
719 char response[2] = {0};
720 auto rc = sendCommand(command, response, -1, 1);
721 return rc && response[0] ==
'1';
727bool LX200AM5::getAltitudeLimitUpper()
729 char response[DRIVER_LEN] = {0};
730 if (sendCommand(
":GLH#", response))
733 if (sscanf(response,
"%d#", &limit) == 1)
735 AltitudeLimitUpperNP[0].setValue(limit);
747bool LX200AM5::setAltitudeLimitLower(
double limit)
749 char command[DRIVER_LEN] = {0};
750 snprintf(command, DRIVER_LEN,
":SLL%02d#",
static_cast<int>(limit));
751 char response[2] = {0};
752 auto rc = sendCommand(command, response, -1, 1);
753 return rc && response[0] ==
'1';
759bool LX200AM5::getAltitudeLimitLower()
761 char response[DRIVER_LEN] = {0};
762 if (sendCommand(
":GLL#", response))
765 if (sscanf(response,
"%d#", &limit) == 1)
767 AltitudeLimitLowerNP[0].setValue(limit);
779bool LX200AM5::clearMultiStarAlignmentData()
781 char response[2] = {0};
782 auto rc = sendCommand(
":NSC#", response, -1, 1);
783 return rc && response[0] ==
'1';
789bool LX200AM5::setVariableSlewRate(
double rate)
791 char command[DRIVER_LEN] = {0};
792 snprintf(command, DRIVER_LEN,
":Rv%.2f#", rate);
793 return sendCommand(command);
801 int h {0}, m {0}, s {0};
802 char command[DRIVER_LEN] = {0};
806 snprintf(command, DRIVER_LEN,
":SG%c%02d:%02d#", offset >= 0 ?
'+' :
'-', std::abs(h), m);
812 char command[DRIVER_LEN] = {0};
813 snprintf(command, DRIVER_LEN,
":SC%02d/%02d/%02d#", months, days, years % 100);
822 char response[DRIVER_LEN] = {0};
823 bool rc = sendCommand(enabled ?
":Te#" :
":Td#", response, 4, 1);
824 return rc && response[0] ==
'1';
830bool LX200AM5::isTracking()
832 char response[DRIVER_LEN] = {0};
833 bool rc = sendCommand(
":GAT#", response);
834 return rc && response[0] ==
'1';
840bool LX200AM5::goHome()
842 return sendCommand(
":hC#");
862bool LX200AM5::setHome()
864 const char cmd[] =
":SOa#";
866 return sendCommand(
cmd, &status, strlen(
cmd),
sizeof(status)) && status ==
'1';
875 int d{0}, m{0}, s{0};
880 longitude = longitude - 360;
882 char command[DRIVER_LEN] = {0};
886 snprintf(command, DRIVER_LEN,
":Sg%c%03d*%02d:%02d#", longitude >= 0 ?
'+' :
'-', std::abs(d), m, s);
889 LOG_ERROR(
"Error setting site longitude coordinates");
894 snprintf(command, DRIVER_LEN,
":St%c%02d*%02d:%02d#", latitude >= 0 ?
'+' :
'-', std::abs(d), m, s);
897 LOG_ERROR(
"Error setting site latitude coordinates");
909 m_MountParking =
false;
913 if (hasCustomParkPosition() && CustomParkSP[0].getState() ==
ISS_ON)
914 rc = parkToMountPosition();
931 char response[DRIVER_LEN] = {0};
932 if (!sendStatusCommand(
":Spu#", response))
938 if (response[0] !=
'1')
942 if (!getMountParkState(state) || state !=
'0')
944 LOGF_ERROR(
"Mount refused to unpark (%s).", response);
960 if (!hasCustomParkPosition())
962 LOGF_WARN(
"Setting the park position requires mount firmware 1.3.0 or later (detected %s).",
963 FirmwareTP[FIRMWARE_VERSION].
getText());
967 char response[DRIVER_LEN] = {0};
968 if (!sendStatusCommand(
":Sp01#", response))
970 LOG_ERROR(
"Failed to set park position.");
977 LOG_INFO(
"Current position is stored as the mount park position.");
980 LOG_INFO(
"Current position is already the mount park position.");
983 LOG_ERROR(
"Mount refused the park position: only one park position can be set.");
986 LOG_ERROR(
"Mount refused the park position: only available in equatorial mode.");
989 LOG_ERROR(
"Mount refused the park position: the mount has to be homed first.");
992 LOG_ERROR(
"Mount refused the park position: the mount is moving.");
995 LOGF_ERROR(
"Mount refused the park position (%s).", response);
1014 LOG_INFO(
"Mount parks at the home position.");
1021bool LX200AM5::parkToMountPosition()
1023 char status[DRIVER_LEN] = {0};
1024 if (!sendCommand(
":GU#", status))
1027 if (strchr(status,
'Z'))
1029 LOG_ERROR(
"Parking to the mount park position is only available in equatorial mode.");
1035 LOG_ERROR(
"Failed to stop tracking before parking.");
1039 m_ParkMoved =
false;
1040 m_ParkDeadline = std::chrono::steady_clock::now() + PARK_START_TIMEOUT;
1042 LOG_INFO(
"Parking to the mount park position...");
1043 m_MountParking = sendCommand(
":hP#");
1044 return m_MountParking;
1050bool LX200AM5::getMountParkState(
char &state)
1052 char response[DRIVER_LEN] = {0};
1053 if (!sendCommand(
":Gps#", response))
1056 state = response[0];
1063void LX200AM5::checkMountParkState()
1065 m_MountParking =
false;
1068 if (!hasMountPark() || !getMountParkState(state))
1073 LOG_INFO(
"Mount reports it is parked.");
1076 else if (state ==
'1')
1080 m_MountParking =
true;
1090void LX200AM5::updateMountPark(
bool slewComplete)
1092 const bool slewing = !slewComplete;
1093 const bool timedOut = std::chrono::steady_clock::now() > m_ParkDeadline;
1097 if (!getMountParkState(state))
1103 m_MountParking =
false;
1114 else if (!m_ParkMoved && timedOut)
1115 failMountPark(
"mount did not start moving to the park position");
1119 failMountPark(
"mount reported a park error");
1127void LX200AM5::failMountPark(
const char *reason)
1130 m_MountParking =
false;
1146 bool slewComplete =
false, isHome =
false;
1147 char status[DRIVER_LEN] = {0};
1148 if (sendCommand(
":GU#", status))
1150 slewComplete = strchr(status,
'N');
1151 isHome = strchr(status,
'H');
1168 LOG_INFO(
"Slew is complete. Tracking...");
1174 updateMountPark(slewComplete);
1175 else if (slewComplete)
1182 auto nowTracking = isTracking();
1183 if (wasTracking != nowTracking)
1197 char response[DRIVER_LEN] = {0};
1198 if (sendCommand(
":Gm#", response))
1200 if (response[0] ==
'W')
1202 else if (response[0] ==
'E')
1217void LX200AM5::getFirmwareInfo()
1219 m_FirmwareVersion = 0;
1221 char response[DRIVER_LEN] = {0};
1222 if (sendCommand(
":GVP#", response))
1224 char *term = strchr(response, DRIVER_STOP_CHAR);
1227 FirmwareTP[FIRMWARE_MODEL].setText(response);
1230 memset(response, 0,
sizeof(response));
1231 if (sendCommand(
":GV#", response))
1233 char *term = strchr(response, DRIVER_STOP_CHAR);
1236 FirmwareTP[FIRMWARE_VERSION].setText(response);
1238 int major = 0, minor = 0, patch = 0;
1239 if (sscanf(response,
"%d.%d.%d", &major, &minor, &patch) == 3)
1240 m_FirmwareVersion = (major << 16) | (minor << 8) | patch;
1242 LOGF_WARN(
"Unexpected firmware version format: %s", response);
1247 LOGF_INFO(
"Mount %s firmware %s.", FirmwareTP[FIRMWARE_MODEL].
getText(), FirmwareTP[FIRMWARE_VERSION].
getText());
1248 if (!hasCustomParkPosition())
1249 LOG_INFO(
"Mount parks at the home position. Custom park position requires firmware 1.3.0 or later.");
1250 else if (CustomParkSP[0].getState() ==
ISS_ON)
1251 LOG_INFO(
"Mount parks at the custom park position.");
1253 LOG_INFO(
"Mount parks at the home position. To use a custom park position, slew to it and set it as current park position.");
1259bool LX200AM5::sendStatusCommand(
const char *
cmd,
char * res)
1261 int nbytes_written = 0, nbytes_read = 0;
1263 tcflush(
PortFD, TCIOFLUSH);
1270 if (rc ==
TTY_OK && res[0] ==
'e')
1281 char *term = strchr(res, DRIVER_STOP_CHAR);
1284 else if (res[0] !=
'e')
1289 tcflush(
PortFD, TCIOFLUSH);
1297bool LX200AM5::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
1299 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1301 tcflush(
PortFD, TCIOFLUSH);
1305 char hex_cmd[DRIVER_LEN * 3] = {0};
1306 hexDump(hex_cmd,
cmd, cmd_len);
1320 LOGF_ERROR(
"Serial write error: %s.", errstr);
1331 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
1339 LOGF_ERROR(
"Serial read error: %s.", errstr);
1345 char hex_res[DRIVER_LEN * 3] = {0};
1346 hexDump(hex_res, res, res_len);
1354 tcflush(
PortFD, TCIOFLUSH);
1376 LOG_WARN(
"Setting home position is not supported by the ZWO AM5 protocol.");
1381 LOG_WARN(
"Finding home position is not supported by the ZWO AM5 protocol.");
1392void LX200AM5::hexDump(
char * buf,
const char * data,
int size)
1394 for (
int i = 0; i < size; i++)
1395 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
1398 buf[3 * size - 1] =
'\0';
1404std::vector<std::string> LX200AM5::split(
const std::string &input,
const std::string ®ex)
1407 std::regex re(regex);
1408 std::sregex_token_iterator
1409 first{input.begin(), input.end(), re, -1},
1411 return {first, last};
1421 MountTypeSP.
save(fp);
1422 GuideRateNP.
save(fp);
1424 HeavyDutyModeSP.
save(fp);
1425 MeridianFlipSP.
save(fp);
1426 PostMeridianTrackSP.
save(fp);
1427 MeridianLimitNP.
save(fp);
1428 AltitudeLimitSP.
save(fp);
1429 AltitudeLimitUpperNP.
save(fp);
1430 AltitudeLimitLowerNP.
save(fp);
1431 VariableSlewRateNP.
save(fp);
1432 CustomParkSP.
save(fp);
void setDefaultHost(const char *addressHost)
void setLANSearchEnabled(bool enabled)
void setDefaultPort(uint32_t addressPort)
INDI::PropertyText getText(const char *name) const
bool updateProperty(PropertyType &property, ValueType *values, char *names[], int n, std::function< bool()> updater, bool saveConfig=false)
Generic helper function to update an INDI property based on an external operation.
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
void setActiveConnection(Connection::Interface *existingConnection)
setActiveConnection Switch the active connection to the passed connection plugin
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)
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 save(FILE *f) const
save Save property to configuration file.
void setLabel(const char *label)
bool isNameMatch(const char *otherName) const
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 fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
TelescopeStatus TrackState
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
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....
Connection::TCP * tcpConnection
@ 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 ReadScopeStatus() override
Read telescope status.
virtual IPState ExecuteHomeAction(TelescopeHomeAction action) override
Execute a homing action.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool SetDefaultPark() override
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
virtual bool initProperties() override
Called to initialize basic properties required all the time.
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 const char * getDefaultName() override
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool checkConnection() override
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
virtual bool setUTCOffset(double offset) override
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
virtual bool SetSlewRate(int index) override
SetSlewRate Set desired slew rate index.
virtual bool setLocalDate(uint8_t days, uint8_t months, uint16_t years) override
virtual bool initProperties() override
Called to initialize basic properties required all the time.
@ LX200_HAS_PULSE_GUIDING
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 saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
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)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * INFO_TAB
INFO_TAB Where all the properties for general information 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,...
INDI::PropertySwitch ParkSP
INDI::PropertyNumber EqNP
INDI::PropertySwitch TrackStateSP
INDI::PropertySwitch HomeSP
INDI::PropertySwitch SlewRateSP
INDI::PropertySwitch TrackModeSP
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 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_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,...)
int setStandardProcedure(int fd, const char *data)
#define getLX200DEC(fd, x)
#define getLX200RA(fd, x)