30#define PRODUCT_NAME "TitanTCS CRUX"
31#define HANDSHAKE_NAME "TiTaN TCS"
32#define MIN_FW_VERSION "3.1.0"
33#define MAX_CMD_LEN 256
35static std::unique_ptr<TitanTCS> titanTCS(
new TitanTCS());
68 bool bResult = Telescope::Connect();
69 LOGF_DEBUG(
"Connect() => %s", (bResult ?
"true" :
"false"));
83 bool bResult = Telescope::Disconnect();
84 LOGF_DEBUG(
"Disconnect() => %s", (bResult ?
"true" :
"false"));
118 IUFillText(&PECInfoT[0],
"PEC_INFO",
"PEC",
"");
119 IUFillText(&PECInfoT[1],
"PEC_TR_INFO",
"Training",
"");
124 IUFillText(&MountInfoT[0],
"MOUNT_PARK",
"Park",
"");
125 IUFillText(&MountInfoT[1],
"MOUNT_TRACKING",
"Tracking",
"");
132 ParkModeSP[PARK_MODE_AT_CURRENT].
fill(
"PARK_MODE_AT_CURRENT",
"At current position",
ISS_OFF);
133 ParkModeSP[PARK_MODE_AT_SAVED].
fill(
"PARK_MODE_AT_SAVED",
"At saved position",
ISS_ON);
163 LOG_INFO(
"Park data loaded from file.");
213 ParkModeSP.
update(states, names, n);
219 LOG_INFO(
"Park mode: lock the mount at its current position.");
221 LOG_INFO(
"Park mode: slew to the saved park position, then lock.");
236 SendCommand(
"#:\\e10#:\\e11#");
238 else if(nowIndex == 1)
240 SendCommand(
"#:\\e12#");
245 if (!strcmp(name, PECTrainingSP.
name))
255 SendCommand(
"#:\\e20#:\\e21#");
257 else if(nowIndex == 1)
259 SendCommand(
"#:\\e23#");
276 else if(nowIndex == 1)
314 if(CommandResponseStr(
"#:GVP#",
"",
'#', szResponse,
sizeof(szResponse)))
316 LOGF_INFO(
"Product Name = '%s'", szResponse);
319 if(CommandResponseStr(
"#:GVN#",
"",
'#', szResponse,
sizeof(szResponse)))
321 LOGF_INFO(
"Firmware Version = '%s'", szResponse);
332 LOG_ERROR(
"The firmware version cannot be read.");
337 LOGF_ERROR(
"TitanTCS could not be found. return code = '%s'", szResponse);
347static int Char2Num(
char chr)
349 if((chr >=
'0') && (chr <=
'9'))
352 if((chr >=
'A') && (chr <=
'F'))
353 return chr -
'A' + 10;
355 if((chr >=
'a') && (chr <=
'f'))
356 return chr -
'a' + 10;
361static int GetDigitParam(
const char *pStr,
int* pDigit,
char* pDelimeter =
nullptr)
372 while (*pStr ==
' ' || *pStr ==
'+')
387 pDigit[cntParam] = sign;
389 pDelimeter[cntParam] = 0;
392 for(i = 0; i < 3; i++)
394 pDigit[cntParam] = 0;
408 pDelimeter[cntParam] = *pStr;
412 pDigit[cntParam] *= 10;
413 pDigit[cntParam] += Char2Num(*pStr);
433static bool HMS2Hour(
const char* pStr,
double* hr)
435 int digit[5] = { 0, 0, 0, 0, 0 };
436 int rtnCode = GetDigitParam(pStr, digit);
439 for(
int i = 1; i < 4; i++)
452static void formatRA(
long secRa,
char* pStr)
461 int h = secRa / 3600;
470 sprintf(pStr,
"-%02d:%02d:%02d", h, m, s);
472 sprintf(pStr,
"%02d:%02d:%02d", h, m, s);
475static void formatDEC(
long secDec,
char* pStr)
477 if (secDec > (270 * 3600))
478 secDec = secDec - (360 * 3600);
479 else if (secDec > (90 * 3600))
480 secDec = (180 * 3600) - secDec;
493 int h = secDec / 3600;
494 secDec -= (h * 3600);
501 sprintf(pStr,
"%c%02d*%02d:%02d", sign, h, m, s);
509 SendCommand(
":Mgn%d#", (
int)ms);
520 GuideNSTID =
IEAddTimer(
static_cast<int>(ms), guideTimeoutHelperNS,
this);
526 SendCommand(
":Mgs%d#", (
int)ms);
537 GuideNSTID =
IEAddTimer(
static_cast<int>(ms), guideTimeoutHelperNS,
this);
543 SendCommand(
":Mge%d#", (
int)ms);
554 GuideWETID =
IEAddTimer(
static_cast<int>(ms), guideTimeoutHelperWE,
this);
560 SendCommand(
":Mgw%d#", (
int)ms);
571 GuideWETID =
IEAddTimer(
static_cast<int>(ms), guideTimeoutHelperWE,
this);
588 if(!SetTarget(
ra,
dec))
593 sprintf(szCommand,
":MS#");
595 if(!CommandResponseChar(szCommand,
"", &rtnCode))
602 LOGF_ERROR(
"Goto / Error Code = '%c'", rtnCode);
613 m_HaveLastPos =
false;
629 return SendCommand(
"#:Q#");
646 GetMountParamsLight();
657bool TitanTCS::GetParamStr(
const char* pInStr,
char* pOutStr,
int len,
const char* pResponse,
char delimeter)
661 if((pResponse != NULL) && (*pResponse == 0))
666 const char* pFind = strstr(pInStr, pResponse);
672 int l = strlen(pResponse);
680 for(
int i = 0; i < 3; i++)
694 snprintf(pOutStr, len,
"%s", pInStr);
698 char* pDel = strchr(pOutStr, delimeter);
713bool TitanTCS::GetParamNumber(
const char* pInStr,
char* pOutStr,
int len,
const char* pResponse,
char delimeter,
714 double *pDouble,
int *pInteger)
716 if(!GetParamStr(pInStr, pOutStr, len, pResponse, delimeter))
720 *pDouble = atof(pOutStr);
722 *pInteger = atoi(pOutStr);
727bool TitanTCS::GetParamHour(
const char* pInStr,
char* pOutStr,
int len,
const char* pResponse,
char delimeter,
730 if(!GetParamStr(pInStr, pOutStr, len, pResponse, delimeter))
734 if(HMS2Hour(pOutStr, pHour))
741bool TitanTCS::SendCommand(
const char *
cmd)
749 int nbytes_written = 0;
754 char titanfocus_error[256];
756 LOGF_ERROR(
"tty_write() error detected: %s", titanfocus_error);
765bool TitanTCS::SendCommand(
const char *
cmd,
int val)
768 sprintf(szBuff,
cmd, val);
770 return SendCommand(szBuff);
773bool TitanTCS::SendCommand(
const char *
cmd,
double val)
776 sprintf(szBuff,
cmd, val);
778 return SendCommand(szBuff);
781void TitanTCS::ReadFlush()
791 for(
int i = 0; i < 3; i++)
806int TitanTCS::ReadResponse(
char *buf,
int len,
char delimeter,
int timeout)
817 for(
int i = 0; i < len; i++)
819 int err_code =
tty_read(
PortFD, buf + recv_len, 1, timeout, &bytesRead);
825 char titanfocus_error[256] = {0};
827 LOGF_ERROR(
"tty_read() error detected: '%s' len %d, %s", buf, recv_len, titanfocus_error);
831 char read_ch = buf[recv_len];
844 if((recv_len + 1) >= len)
846 LOGF_ERROR(
"TTY error detected: overflow %d, %d", recv_len, len);
853 if(read_ch == delimeter)
863bool TitanTCS::CommandResponse(
const char* pCommand,
const char* pResponse,
char delimeter,
double *pDouble,
int *pInteger)
866 if (!SendCommand(pCommand))
872 int rd_count = ReadResponse(szResponse,
sizeof(szResponse), delimeter);
880 if(!GetParamNumber(szResponse, szResult,
sizeof(szResult) - 1, pResponse, delimeter, pDouble, pInteger))
882 LOGF_DEBUG(
"CommandResponse('%s', '%s') Fail!", pCommand, pResponse);
889bool TitanTCS::CommandResponseHour(
const char* pCommand,
const char* pResponse,
char delimeter,
double* Hour)
892 if (!SendCommand(pCommand))
898 int rd_count = ReadResponse(szResponse,
sizeof(szResponse), delimeter);
906 if(!GetParamHour(szResponse, szResult,
sizeof(szResult) - 1, pResponse, delimeter, Hour))
908 LOGF_DEBUG(
"CommandResponseHour('%s', '%s') Fail!", pCommand, pResponse);
915bool TitanTCS::CommandResponseStr(
const char* pCommand,
const char* pResponse,
char delimeter,
char* pReturn,
int len)
918 if (!SendCommand(pCommand))
923 int rd_count = ReadResponse(szResponse,
sizeof(szResponse), delimeter);
931 if(!GetParamStr(szResponse, pReturn, len, pResponse, delimeter))
933 LOGF_DEBUG(
"CommandResponseStr('%s', '%s') Fail!", pCommand, pResponse);
942bool TitanTCS::CommandResponseChar(
const char* pCommand,
const char* pResponse,
char* pReturn)
945 if (!SendCommand(pCommand))
951 int rd_count = ReadResponse(szResponse, 1, 0);
959 if(!GetParamStr(szResponse, szResult,
sizeof(szResult) - 1, pResponse, 0))
961 LOGF_DEBUG(
"CommandResponseChar('%s', '%s') Fail!", pCommand, pResponse);
965 *pReturn = szResult[0];
972bool TitanTCS::SetTarget(
double ra,
double dec)
975 formatRA(
ra * 3600, szRA);
976 formatDEC(
dec * 3600, szDEC);
981 sprintf(szCommand,
"#:Sr %s#", szRA);
982 if(!CommandResponseChar(szCommand,
"", &rtnCode))
989 LOGF_ERROR(
"SetTarget DEC / Error Code = '%c'", rtnCode);
993 sprintf(szCommand,
"#:Sd %s#", szDEC);
994 if(!CommandResponseChar(szCommand,
"", &rtnCode))
996 LOG_ERROR(
"SetTarget DEC / No response");
1001 LOGF_ERROR(
"SetTarget DEC / Error Code = '%c'", rtnCode);
1005 LOGF_INFO(
"Set target RA:%s, DEC:%s", szRA, szDEC);
1009void TitanTCS::guideTimeoutNS()
1018void TitanTCS::guideTimeoutWE()
1027void TitanTCS::guideTimeoutHelperNS(
void * p)
1029 static_cast<TitanTCS *
>(p)->guideTimeoutNS();
1032void TitanTCS::guideTimeoutHelperWE(
void * p)
1034 static_cast<TitanTCS *
>(p)->guideTimeoutWE();
1037bool TitanTCS::GetMountParamsLight()
1043 double ra = 0,
dec = 0;
1046 if(!CommandResponseHour(
"#:GR#",
"",
'#', &
ra))
1048 LOG_ERROR(
"GetMountParamsLight: failed to read RA");
1053 if(!CommandResponseHour(
"#:GD#",
"",
'#', &
dec))
1055 LOG_ERROR(
"GetMountParamsLight: failed to read DEC");
1072 double dRA = fabs(
ra - m_LastRA);
1073 double dDEC = fabs(
dec - m_LastDEC);
1080 bool stable = (dRA < 0.01 && dDEC < 0.01);
1085 if(m_StableCount >= 2)
1088 m_HaveLastPos =
false;
1090 LOG_DEBUG(
"Slew/park appears complete, querying full status");
1103 m_HaveLastPos =
true;
1108bool TitanTCS::GetMountParams(
bool bAll)
1114 char szCommand[256];
1115 sprintf(szCommand,
"#:\\GE($GR #:GR#"
1122 ":\\GE%d)#", cnt++);
1126 char szResponse[256];
1127 if(!CommandResponseStr(szCommand,
"(",
')', szResponse,
sizeof(szResponse) - 1))
1132 if(GetParamHour(szResponse, szToken,
sizeof(szToken) - 1,
"$GR",
'#', &info.
ra))
1134 if(GetParamHour(szResponse, szToken,
sizeof(szToken) - 1,
"$GD",
'#', &info.
dec))
1153 if(GetParamNumber(szResponse, szToken,
sizeof(szToken) - 1,
"$?pe",
'#', NULL, &info.
PECStatus))
1161 if(GetParamNumber(szResponse, szToken,
sizeof(szToken) - 1,
"$?ts",
'#', NULL, &info.
TrackingStatus))
1182 SendCommand(
"#:Q#");
1191 SendCommand(
"#:Q#");
1204 if(GetParamNumber(szResponse, szToken,
sizeof(szToken) - 1,
"$hP",
'#', NULL, &info.
Parking))
1254 if(GetParamNumber(szResponse, szToken,
sizeof(szToken) - 1,
"$?tm",
'#', NULL, &info.
Landscape))
1265 IUSaveText(&MountInfoT[1],
"Tracking ON / Skyview");
1275 IUSaveText(&MountInfoT[1],
"Tracking OFF / Landscape");
1277 IUSaveText(&MountInfoT[1],
"Tracking OFF / Idle");
1285 if(GetParamNumber(szResponse, szToken,
sizeof(szToken) - 1,
"$?tr",
'#', NULL, &info.
TrackingRate))
1295 static int prev_TrackState = -1;
1309 LOG_INFO(
"Track State : TRACKING");
1323void TitanTCS::_setPECState(
int pec_status)
1325 if (_PECStatus != pec_status)
1330 _PECStatus = pec_status;
1336 if(pec_status & 0x30)
1340 PECTrainingS[1].s =
ISS_ON;
1342 sprintf(szText,
"PEC Training %d %%", (pec_status >> 8));
1347 PECTrainingS[0].s =
ISS_ON;
1368 IUSaveText(&PECInfoT[0],
"PEC is available.");
1379 if(pec_status & 0x30)
1382 IUSaveText(&PECInfoT[0],
"PEC training is required.");
1405 double JD = ln_get_julian_day(utc);
1409 ln_date_to_zonedate(utc, <m, utc_offset * 3600);
1411 LOGF_DEBUG(
"Local time is %02d:%02d:%02g", ltm.hours, ltm.minutes, ltm.seconds);
1414 sprintf(szText,
"#:SG %.1f#:SC %02d/%02d/%02d#:SL %02d:%02d:%02d#",
1416 ltm.months, ltm.days, ltm.years % 100,
1417 ltm.hours, ltm.minutes, (
int)ltm.seconds % 60);
1421 return SendCommand(szText);
1429 if((fabs(latitude) < 0.001) && (fabs(longitude) < 0.001))
1432 int d = 0, m = 0, s = 0;
1433 char szCommand[128];
1437 sprintf(szCommand,
"#:St %03d:%02d:%02d#", d, m, s);
1438 LOGF_INFO(
"Set latitude '%s'", szCommand);
1439 if(!CommandResponseChar(szCommand, NULL, &rtnCode))
1443 sprintf(szCommand,
"#:Sg %03d:%02d:%02d#", d, m, s);
1444 LOGF_INFO(
"Set longitude '%s'", szCommand);
1445 return CommandResponseChar(szCommand, NULL, &rtnCode);
1450 if(!SetTarget(
ra,
dec))
1453 char rtnCode[64] = {
"" };
1455 sprintf(szCommand,
":CM#");
1457 if(!CommandResponseStr(szCommand,
"",
'#', rtnCode,
sizeof(rtnCode) - 1))
1462 if(strcmp(rtnCode,
"1") != 0)
1464 LOGF_ERROR(
"Sync / Error Code = '%s'", rtnCode);
1492 sprintf(szCommand,
":M%c#", chDir);
1496 sprintf(szCommand,
":Q%c#", chDir);
1500 LOGF_INFO(
"Moving command:%s", szCommand);
1501 return SendCommand(szCommand);
1525 sprintf(szCommand,
":M%c#", chDir);
1529 sprintf(szCommand,
":Q%c#", chDir);
1533 LOGF_INFO(
"Moving command:%s", szCommand);
1534 return SendCommand(szCommand);
1551 const char *
cmd = atCurrent ?
":hP8#" :
":hP1#";
1553 LOGF_INFO(
"Parking (%s) ...", atCurrent ?
"at current position" :
"to saved park point");
1555 if(!SendCommand(
cmd))
1562 m_HaveLastPos =
false;
1571 if(SendCommand(
":hP0#"))
1587 return SendCommand(
"#:\\T%d#", mode);
1603 return SendCommand(
"#:\\t0#");
1608 return SendCommand(
"#:\\t1#");
1619 LOGF_INFO(
"Park position set to HA %.4f h, DEC %.4f deg", Axis1Value, Axis2Value);
1634 if(!SendCommand(
":hS#"))
1636 LOG_ERROR(
"SetCurrentPark: failed to send save-park command (:hS#)");
1639 LOG_INFO(
"Saved current position as the mount's park point (:hS#).");
1659 LOGF_INFO(
"Default park position set: HA 0.0 h, DEC %.1f deg (pole)", poleDec);
1670 return SendCommand(
":RS#");
1672 return SendCommand(
":RM#");
1674 return SendCommand(
":RC#");
1676 return SendCommand(
":RG#");
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
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
uint32_t getDriverInterface() const
void addDebugControl()
Add Debug control to the driver.
INDI::PropertyNumber GuideNSNP
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
INDI::PropertyNumber GuideWENP
void initProperties(const char *groupName)
Initialize guider properties. It is recommended to call this function within initProperties() of your...
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Call this function whenever client updates GuideNSNP or GuideWSP properties in the primary device....
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.
const char * getName() const
bool isNameMatch(const char *otherName) const
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)
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.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
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....
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
@ TELESCOPE_HAS_PIER_SIDE
@ TELESCOPE_HAS_TRACK_MODE
@ TELESCOPE_CAN_CONTROL_TRACK
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 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.
TelescopePierSide expectedPierSide(double ra)
Calculate the expected pier side for scopes that do not report this property themselves.
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.
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool Disconnect() override
Disconnect from device.
virtual bool Park() override
Park the telescope to its home position.
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool ISNewText(const char *dev, const char *name, char **texts, char **names, int n) override
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
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 SetParkPosition(double Axis1Value, double Axis2Value) override
SetParkPosition Set desired parking position to the supplied value. This ONLY sets the desired park p...
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
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
Update telescope location settings.
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool SetSlewRate(int index) override
SetSlewRate Set desired slew rate index.
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
virtual bool updateTime(ln_date *utc, double utc_offset) override
Update telescope time, date, and UTC offset.
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual const char * getDefaultName() override
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
virtual bool Goto(double ra, double dec) override
Move the scope to the supplied RA and DEC coordinates.
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 * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
void IERmTimer(int timerid)
Remove the timer with the given timerid, as returned from IEAddTimer() or IEAddPeriodicTimer().
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
INDI::PropertySwitch ParkSP
INDI::PropertySwitch MovementNSSP
INDI::PropertySwitch TrackStateSP
INDI::PropertySwitch PECStateSP
INDI::PropertySwitch TrackModeSP
INDI::PropertySwitch MovementWESP
INDI::PropertyNumber LocationNP
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
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
double get_local_hour_angle(double sideral_time, double ra)
get_local_hour_angle Returns local hour angle of an object
Implementations for common driver routines.
double get_local_sidereal_time(double longitude)
get_local_sidereal_time Returns local sidereal time given longitude and system clock.
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 IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
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 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 IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
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,...)