24#include <libnova/julian_day.h>
37 {
"0010",
"SkyHunter EQ"},
38 {
"0011",
"SkyHunter AA"},
51 {
"0032",
"HAE29-EC AA"},
53 {
"0034",
"HAE29-EC AA"},
55 {
"0036",
"HAE29C EQ"},
56 {
"0037",
"HAE29C-EC EQ"},
57 {
"0038",
"HAE29C AA"},
58 {
"0039",
"HAE29C-EC EQ"},
64 {
"0047",
"HEM44A-EC"},
66 {
"0049",
"HAE43-EC EQ"},
68 {
"0051",
"HAE43-EC AA"},
70 {
"0053",
"HAE43C EQ"},
71 {
"0054",
"HAE43C-EC EQ"},
72 {
"0055",
"HAE43C AA"},
73 {
"0056",
"HAE43C-EC AA"},
77 {
"0063",
"HAZ69-EC EQ"},
79 {
"0065",
"HAE69-EC AA"},
80 {
"0066",
"HAE69C EQ"},
81 {
"0067",
"HAE69C-EC EQ"},
82 {
"0068",
"HAE69C AA"},
83 {
"0069",
"HAE69C-EC AA"},
86 {
"0072",
"CEM70-EC2"},
89 {
"0121",
"CEM120-EC"},
90 {
"0122",
"CEM120-EC2"},
91 {
"5010",
"Cube II AA"},
92 {
"5035",
"AZ Mount Pro"},
93 {
"5045",
"iEQ45 Pro AA"}
102 char res[IOP_BUFFER] = {0};
105 return res[0] ==
'1';
119 int nbytes_written = 0;
121 char res[IOP_BUFFER] = {0};
123 DEBUGFDEVICE(m_DeviceName, debugLog,
"CMD <%s>", command);
129 for (
int i = 0; i < 2; i++)
131 tcflush(PortFD, TCIOFLUSH);
133 if ((errCode =
tty_write(PortFD, command, strlen(command), &nbytes_written)) !=
TTY_OK)
146 errCode =
tty_read(PortFD, res, count, timeout, &nbytes_read);
148 if (errCode ==
TTY_OK && (minimumCount < 0 || minimumCount <= count))
161 res[nbytes_read - 1] = 0;
165 tcflush(PortFD, TCIOFLUSH);
169 snprintf(response, IOP_BUFFER,
"%s", res);
176 char res[IOP_BUFFER] = {0};
186 for (
int i = 0; i < 2; i++)
188 if (
sendCommand(
":MountInfo#", 4, res, -1, 3) ==
false)
208 m_Simulation = enable;
214 simData.JD = ln_get_julian_from_sys();
215 simData.utc_offset_minutes = 3 * 60;
216 simData.day_light_saving =
false;
225 simData.simInfo.longitude = 48.1;
226 simData.simInfo.latitude = 29.5;
231 simData.simInfo.gpsStatus = value;
236 simData.simInfo.systemStatus = value;
241 simData.simInfo.trackRate = value;
246 simData.simInfo.slewRate = value;
251 simData.simInfo.timeSource = value;
256 simData.simInfo.hemisphere = value;
271 simData.ra_guide_rate = raRate;
272 simData.de_guide_rate = deRate;
277 simData.simInfo.longitude = longitude;
278 simData.simInfo.latitude = latitude;
283 char res[IOP_BUFFER] = {0};
287 int iopLongitude =
simData.simInfo.longitude * 360000;
288 int iopLatitude = (
simData.simInfo.latitude + 90) * 360000;
289 snprintf(res, IOP_BUFFER,
"%c%08d%08d%d%d%d%d%d%d",
simData.simInfo.longitude > 0 ?
'+' :
'-',
290 iopLongitude, iopLatitude,
simData.simInfo.gpsStatus,
simData.simInfo.systemStatus,
simData.simInfo.trackRate,
293 else if (
sendCommand(
":GLS#", -1, res, 23) ==
false)
297 if (strlen(res) != 23)
304 char longPart[16] = {0}, latPart[16] = {0};
305 snprintf(longPart,
sizeof(longPart),
"%.9s", res);
306 snprintf(latPart,
sizeof(latPart),
"%.8s", res + 9);
308 int arcsecLongitude = atoi(longPart);
309 int arcsecLatitude = atoi(latPart);
311 info->
longitude = arcsecLongitude / 360000.0;
312 info->
latitude = arcsecLatitude / 360000.0 - 90.0;
331 return (rc1 && rc2 && rc3);
336 char res[IOP_BUFFER] = {0};
340 else if (
sendCommand(
":MountInfo#", 4, res) ==
false)
353 char res[IOP_BUFFER] = {0};
356 strcpy(res,
"180321171001");
360 char mStr[16] = {0}, cStr[16] = {0};
361 snprintf(mStr,
sizeof(mStr),
"%.6s", res);
362 snprintf(cStr,
sizeof(cStr),
"%.6s", res + 6);
365 controllerFirmware = cStr;
372 char res[IOP_BUFFER] = {0};
375 strcpy(res,
"140324140101");
379 char mStr[16] = {0}, cStr[16] = {0};
380 snprintf(mStr,
sizeof(mStr),
"%.6s", res);
381 snprintf(cStr,
sizeof(cStr),
"%.6s", res + 6);
455 char res[IOP_BUFFER] = {0};
484 char cmd[IOP_BUFFER] = {0};
485 snprintf(
cmd, IOP_BUFFER,
":SR%u#",
static_cast<uint32_t
>(rate + 1));
487 simData.simInfo.slewRate = rate;
494 simData.simInfo.trackRate = rate;
515 if (rate < 0.1 || rate > 1.9)
518 char cmd[IOP_BUFFER] = {0};
519 snprintf(
cmd, IOP_BUFFER,
":RR%05u#",
static_cast<uint32_t
>(rate * 10000));
526 if (RARate < 0.01 || RARate > 0.9 || DERate < 0.01 || DERate > 0.9)
529 char cmd[IOP_BUFFER] = {0};
530 snprintf(
cmd, IOP_BUFFER,
":RG%02u%02u#",
static_cast<uint32_t
>(RARate * 100),
static_cast<uint32_t
>(DERate * 100));
537 char res[IOP_BUFFER] = {0};
540 snprintf(res, IOP_BUFFER,
"%02u%02u",
static_cast<uint32_t
>(
simData.ra_guide_rate * 100),
541 static_cast<uint32_t
>(
simData.de_guide_rate * 100));
545 char raStr[8] = {0}, deStr[8] = {0};
546 snprintf(raStr,
sizeof(raStr),
"%.2s", res);
547 snprintf(deStr,
sizeof(deStr),
"%.2s", res + 2);
549 *RARate = atoi(raStr) / 100.0;
550 *DERate = atoi(deStr) / 100.0;
557 char cmd[IOP_BUFFER] = {0};
583 snprintf(
cmd, IOP_BUFFER,
":Z%c%05u#", dir_c, ms);
603 char cmd[IOP_BUFFER] = {0};
606 int ieqValue =
static_cast<int>(az * 60 * 60 * 100);
608 snprintf(
cmd, IOP_BUFFER,
":SPA%09d#", ieqValue);
615 char cmd[IOP_BUFFER] = {0};
617 alt = std::max(0.0, alt);
620 int ieqValue =
static_cast<int>(alt * 60 * 60 * 100);
621 snprintf(
cmd, IOP_BUFFER,
":SPH%08d#", ieqValue);
628 simData.simInfo.systemStatus =
simData.simInfo.rememberSystemStatus;
635 simData.simInfo.rememberSystemStatus =
simData.simInfo.systemStatus;
643 simData.simInfo.rememberSystemStatus =
simData.simInfo.systemStatus;
657 char cmd[IOP_BUFFER] = {0};
658 snprintf(
cmd, IOP_BUFFER,
":ST%d#", enabled ? 1 : 0);
667 uint32_t casRA =
ra * 15 * 60 * 60 * 100;
671 char cmd[IOP_BUFFER] = {0};
672 snprintf(
cmd, IOP_BUFFER,
":SRA%09u#", casRA);
681 uint32_t casDE = fabs(
de) * 60 * 60 * 100;
685 char cmd[IOP_BUFFER] = {0};
686 snprintf(
cmd, IOP_BUFFER,
":Sd%c%08u#",
de >= 0 ?
'+' :
'-', casDE);
693 uint32_t casLongitude = fabs(longitude) * 60 * 60 * 100;
695 simData.simInfo.longitude = longitude;
697 char cmd[IOP_BUFFER] = {0};
698 snprintf(
cmd, IOP_BUFFER,
":SLO%c%08u#", longitude >= 0 ?
'+' :
'-', casLongitude);
705 uint32_t casLatitude = fabs(latitude) * 60 * 60 * 100;
707 simData.simInfo.latitude = latitude;
709 char cmd[IOP_BUFFER] = {0};
710 snprintf(
cmd, IOP_BUFFER,
":SLA%c%08u#", latitude >= 0 ?
'+' :
'-', casLatitude);
717 uint64_t msJD = (
JD -
J2000) * 8.64e+7;
719 char cmd[IOP_BUFFER] = {0};
720 snprintf(
cmd, IOP_BUFFER,
":SUT%013" PRIu64
"#", msJD);
729 char cmd[IOP_BUFFER] = {0};
730 snprintf(
cmd, IOP_BUFFER,
":SG%c%03d#", offsetMinutes >= 0 ?
'+' :
'-', abs(offsetMinutes));
732 simData.utc_offset_minutes = offsetMinutes;
739 char cmd[IOP_BUFFER] = {0};
740 snprintf(
cmd, IOP_BUFFER,
":SDS%c#", enabled ?
'1' :
'0');
742 simData.day_light_saving = enabled;
749 char res[IOP_BUFFER] = {0};
752 snprintf(res, IOP_BUFFER,
"%c%08u%09u%d%d", (
simData.de >= 0 ?
'+' :
'-'),
753 static_cast<uint32_t
>(fabs(
simData.de) * 60 * 60 * 100),
759 if (strlen(res) != 20)
766 char deStr[16] = {0}, raStr[16] = {0};
768 strncpy(deStr, res, 9);
769 snprintf(raStr,
sizeof(raStr),
"%.9s", res + 9);
773 *
de = std::atoi(deStr) / (60.0 * 60.0 * 100.0);
774 *
ra = std::atoi(raStr) / (15.0 * 60.0 * 60.0 * 100.0);
790 char res[IOP_BUFFER] = {0};
793 snprintf(res, IOP_BUFFER,
"%c%03d%c%013" PRIu64, (
simData.utc_offset_minutes >= 0 ?
'+' :
'-'),
794 abs(
simData.utc_offset_minutes),
795 (
simData.day_light_saving ?
'1' :
'0'),
static_cast<uint64_t
>((
simData.JD -
J2000) * 8.64e+7));
797 else if (
sendCommand(
":GUT#", -1, res, 18) ==
false)
800 if (strlen(res) != 18)
807 char offsetStr[16] = {0}, JDStr[16] = {0};
809 strncpy(offsetStr, res, 4);
810 snprintf(JDStr,
sizeof(JDStr),
"%.13s", res + 5);
812 *utcOffsetMinutes = atoi(offsetStr);
813 *dayLightSaving = (res[4] ==
'1');
817 uint64_t iopJD = std::stoull(JDStr);
818 *
JD = (iopJD / 8.64e+7) +
J2000;
831 char res[IOP_BUFFER] = {0};
834 snprintf(res, IOP_BUFFER,
"%d%02d",
simData.mb_state,
simData.mb_limit);
842 degrees = std::stoi(res + 1);
862 char cmd[IOP_BUFFER] = {0};
863 snprintf(
cmd, IOP_BUFFER,
":SMT%d%02d#", action, degrees);
bool setTrackMode(IOP_TRACK_RATE rate)
void setSimulation(bool enable)
static const std::map< std::string, std::string > models
bool setPETEnabled(bool enabled)
bool setCustomRATrackRate(double rate)
bool setDaylightSaving(bool enabled)
struct IOPv3::Driver::@350 simData
bool startGuide(IOP_DIRECTION dir, uint32_t ms)
bool getUTCDateTime(double *JD, int *utcOffsetMinutes, bool *dayLightSaving)
bool setMeridianBehavior(IOP_MB_STATE action, uint8_t degrees)
void setSimGPSstatus(IOP_GPS_STATUS value)
void setSimSlewRate(IOP_SLEW_RATE value)
bool getPETEnabled(bool enabled)
bool getGuideRate(double *RARate, double *DERate)
bool getRADEFirmware(std::string &RAFirmware, std::string &DEFirmware)
bool setGuideRate(double RARate, double DERate)
void setSimTrackRate(IOP_TRACK_RATE value)
bool getStatus(IOPInfo *info)
bool sendCommand(const char *command, int count=1, char *response=nullptr, int minimumCount=-1, uint8_t timeout=IOP_TIMEOUT, uint8_t debugLog=INDI::Logger::DBG_DEBUG)
void setSimTimeSource(IOP_TIME_SOURCE value)
void setSimGuideRate(double raRate, double deRate)
bool setParkAz(double az)
bool setParkAlt(double alt)
bool setLatitude(double latitude)
Driver(const char *deviceName)
bool setLongitude(double longitude)
bool getCoords(double *ra, double *de, IOP_PIER_STATE *pierState, IOP_CW_STATE *cwState)
bool sendCommandOk(const char *command)
void setDebug(bool enable)
bool getMeridianBehavior(IOP_MB_STATE &action, uint8_t °rees)
bool stopMotion(IOP_DIRECTION dir)
bool setTrackEnabled(bool enabled)
bool setSlewRate(IOP_SLEW_RATE rate)
bool checkConnection(int fd)
void setSimHemisphere(IOP_HEMISPHERE value)
bool setUTCDateTime(double JD)
void setSimSytemStatus(IOP_SYSTEM_STATUS value)
void setSimLongLat(double longitude, double latitude)
bool setUTCOffset(int offsetMinutes)
bool getFirmwareInfo(FirmwareInfo *info)
bool setPECEnabled(bool enabled)
bool startMotion(IOP_DIRECTION dir)
static const uint16_t IOP_SLEW_RATES[]
bool getMainFirmware(std::string &mainFirmware, std::string &controllerFirmware)
bool getModel(std::string &model)
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
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.
Implementations for common driver routines.
#define DEBUGDEVICE(device, priority, msg)
#define DEBUGFDEVICE(device, priority, msg,...)
Encapsulates classes and structures required for iOptron Command Set v3 implementation.
std::string ControllerFirmware
std::string MainBoardFirmware
IOP_HEMISPHERE hemisphere
IOP_SYSTEM_STATUS systemStatus
IOP_TIME_SOURCE timeSource