25 #include <libnova/sidereal_time.h>
26 #include <libnova/transform.h>
37 #define MOUNTINFO_TAB "Mount Info"
42 static std::unique_ptr<IEQPro> scope(
new IEQPro());
48 driver.reset(
new Base());
53 scopeInfo.slewRate =
SR_1;
59 SetTelescopeCapability(TELESCOPE_CAN_PARK | TELESCOPE_CAN_SYNC | TELESCOPE_CAN_GOTO | TELESCOPE_CAN_ABORT |
60 TELESCOPE_HAS_TIME | TELESCOPE_HAS_LOCATION | TELESCOPE_HAS_TRACK_MODE | TELESCOPE_CAN_CONTROL_TRACK |
61 TELESCOPE_HAS_TRACK_RATE,
84 AddTrackMode(
"TRACK_SIDEREAL",
"Sidereal",
true);
85 AddTrackMode(
"TRACK_LUNAR",
"Lunar");
86 AddTrackMode(
"TRACK_SOLAR",
"Solar");
87 AddTrackMode(
"TRACK_KING",
"King");
88 AddTrackMode(
"TRACK_CUSTOM",
"Custom");
107 TrackRateN[
AXIS_DE].min = -0.01;
108 TrackRateN[
AXIS_DE].max = 0.01;
134 IUFillSwitchVector(&HomeSP, HomeS, 3,
getDeviceName(),
"HOME",
"Home",
MAIN_CONTROL_TAB,
IP_RW,
ISR_ATMOST1, 0,
143 TrackState = SCOPE_IDLE;
147 setDriverInterface(getDriverInterface() | GUIDER_INTERFACE);
149 SetParkDataType(PARK_AZ_ALT);
160 currentDEC = LocationN[LOCATION_LATITUDE].value > 0 ? 90 : -90;
177 defineProperty(&HomeSP);
179 defineProperty(&GuideNSNP);
180 defineProperty(&GuideWENP);
183 defineProperty(&GuideRateNP);
185 defineProperty(&FirmwareTP);
186 defineProperty(&GPSStatusSP);
187 defineProperty(&TimeSourceSP);
188 defineProperty(&HemisphereSP);
195 deleteProperty(HomeSP.name);
197 deleteProperty(GuideNSNP.name);
198 deleteProperty(GuideWENP.name);
201 deleteProperty(GuideRateNP.name);
203 deleteProperty(FirmwareTP.name);
204 deleteProperty(GPSStatusSP.name);
205 deleteProperty(TimeSourceSP.name);
206 deleteProperty(HemisphereSP.name);
212 void IEQPro::getStartupData()
216 firmwareInfo = driver->getFirmwareInfo();
218 IUSaveText(&FirmwareT[0], firmwareInfo.Model.c_str());
219 IUSaveText(&FirmwareT[1], firmwareInfo.MainBoardFirmware.c_str());
220 IUSaveText(&FirmwareT[2], firmwareInfo.ControllerFirmware.c_str());
221 IUSaveText(&FirmwareT[3], firmwareInfo.RAFirmware.c_str());
222 IUSaveText(&FirmwareT[4], firmwareInfo.DEFirmware.c_str());
229 double raGuideRate = 0, deGuideRate = 0;
230 if (driver->getGuideRate(&raGuideRate, &deGuideRate))
232 GuideRateN[
RA_AXIS].value = raGuideRate;
233 GuideRateN[
DEC_AXIS].value = deGuideRate;
238 int yy, dd, mm, hh, minute, ss;
239 if (driver->getUTCDateTime(&utc_offset, &yy, &mm, &dd, &hh, &minute, &ss))
241 char isoDateTime[32] = {0};
242 char utcOffset[8] = {0};
244 snprintf(isoDateTime, 32,
"%04d-%02d-%02dT%02d:%02d:%02d", yy, mm, dd, hh, minute, ss);
245 snprintf(utcOffset, 8,
"%4.2f", utc_offset);
250 LOGF_INFO(
"Mount UTC offset is %s. UTC time is %s", utcOffset, isoDateTime);
257 double longitude = 0, latitude = 0;
258 if (driver->getStatus(&scopeInfo))
260 longitude = scopeInfo.longitude;
261 latitude = scopeInfo.latitude;
267 LOGF_INFO(
"Mount Longitude %g Latitude %g", longitude, latitude);
269 LocationN[LOCATION_LATITUDE].value = latitude;
270 LocationN[LOCATION_LONGITUDE].value = longitude;
275 saveConfig(
true,
"GEOGRAPHIC_COORD");
280 LocationN[LOCATION_LATITUDE].value = latitude;
281 LocationN[LOCATION_LONGITUDE].value = longitude;
290 SetAxis1ParkDefault(LocationN[LOCATION_LATITUDE].value >= 0 ? 0 : 180);
291 SetAxis2ParkDefault(LocationN[LOCATION_LATITUDE].value);
296 SetAxis1Park(LocationN[LOCATION_LATITUDE].value >= 0 ? 0 : 180);
297 SetAxis2Park(LocationN[LOCATION_LATITUDE].value);
298 SetAxis1ParkDefault(LocationN[LOCATION_LATITUDE].value >= 0 ? 0 : 180);
299 SetAxis2ParkDefault(LocationN[LOCATION_LATITUDE].value);
307 auto cap = GetTelescopeCapability();
308 cap |= TELESCOPE_HAS_PIER_SIDE;
309 SetTelescopeCapability(cap, 9);
326 if (!strcmp(name, GuideRateNP.name))
330 if (driver->setGuideRate(GuideRateN[
RA_AXIS].value, GuideRateN[
DEC_AXIS].value))
340 if (!strcmp(name, GuideNSNP.name) || !strcmp(name, GuideWENP.name))
342 processGuiderProperties(name, values, names, n);
354 if (!strcmp(name, HomeSP.name))
365 if (driver->setCurrentHome() ==
false)
374 LOG_INFO(
"Home position set to current coordinates.");
378 if (TrackState == SCOPE_PARKED)
380 LOG_ERROR(
"Please unpark the mount before issuing any motion commands.");
384 if (driver->gotoHome() ==
false)
393 LOG_INFO(
"Slewing to home position...");
397 if (driver->findHome() ==
false)
406 LOG_INFO(
"Searching for home position...");
424 bool rc = driver->getStatus(&newInfo);
470 if (canParkNatively || TrackState != SCOPE_PARKED)
471 TrackState = SCOPE_IDLE;
475 TrackState = SCOPE_PARKED;
481 TrackState = SCOPE_IDLE;
486 if (TrackState != SCOPE_SLEWING && TrackState != SCOPE_PARKING)
487 TrackState = SCOPE_SLEWING;
492 if (TrackState == SCOPE_PARKING && canParkNatively ==
false)
496 LOG_INFO(
"Manual parking complete. Shut the mount down.");
498 TrackState = SCOPE_PARKED;
499 SetTrackEnabled(
false);
507 TrackState = SCOPE_TRACKING;
509 LOG_INFO(
"Slew complete, tracking...");
511 LOG_INFO(
"Meridian flip complete, tracking...");
526 if (driver->getPierSide(&pierSide))
558 char RAStr[64] = {0}, DecStr[64] = {0};
560 fs_sexa(RAStr, targetRA, 2, 3600);
561 fs_sexa(DecStr, targetDEC, 2, 3600);
563 if (driver->setRA(r) ==
false || driver->setDE(d) ==
false)
569 if (driver->slew() ==
false)
579 for (
int i = 0; i < 5; i++)
581 bool rc = driver->getStatus(&newInfo);
584 std::this_thread::sleep_for(std::chrono::milliseconds(100));
589 TrackState = SCOPE_SLEWING;
590 LOGF_INFO(
"Slewing to RA: %s - DEC: %s", RAStr, DecStr);
595 LOG_ERROR(
"Mount status failed to update to slewing.");
602 if (driver->setRA(
ra) ==
false || driver->setDE(
dec) ==
false)
608 if (driver->sync() ==
false)
625 return driver->abort();
631 targetRA = GetAxis1Park();
632 targetDEC = GetAxis2Park();
642 LOG_ERROR(
"Failed to slew tp parking position.");
646 char RAStr[64] = {0}, DecStr[64] = {0};
647 fs_sexa(RAStr, targetRA, 2, 3600);
648 fs_sexa(DecStr, targetDEC, 2, 3600);
650 TrackState = SCOPE_PARKING;
651 LOGF_INFO(
"Telescope parking in progress to RA: %s DEC: %s", RAStr, DecStr);
656 double parkAz = GetAxis1Park();
657 double parkAlt = GetAxis2Park();
659 char AzStr[16], AltStr[16];
660 fs_sexa(AzStr, parkAz, 2, 3600);
661 fs_sexa(AltStr, parkAlt, 2, 3600);
662 LOGF_DEBUG(
"Parking to Az (%s) Alt (%s)...", AzStr, AltStr);
667 if (driver->setParkAz(parkAz) && driver->setParkAlt(parkAlt))
671 TrackState = SCOPE_PARKING;
672 LOG_INFO(
"Parking is in progress...");
684 horizontalPos.
azimuth = parkAz;
692 TrackState = SCOPE_PARKING;
693 LOG_INFO(
"Parking is in progress...");
707 if (canParkNatively && driver->unpark() ==
false)
711 TrackState = SCOPE_IDLE;
727 if (driver->initCommunication(PortFD) ==
false)
730 canParkNatively = driver->isCommandSupported(
"MP1",
true);
731 canFindHome = driver->isCommandSupported(
"MSH",
true);
732 canGuideRate = driver->isCommandSupported(
"RG",
true);
739 struct ln_zonedate ltm;
741 ln_date_to_zonedate(utc, <m, utc_offset * 3600.0);
744 if (driver->setLocalTime(ltm.hours, ltm.minutes, ltm.seconds) ==
false)
754 if (driver->setLocalDate(ltm.years, ltm.months, ltm.days) ==
false)
761 if (driver->setUTCOffset(utc_offset) ==
false)
779 if (driver->setLongitude(longitude) ==
false)
785 if (driver->setLatitude(latitude) ==
false)
791 char l[32] = {0}, L[32] = {0};
793 fs_sexa(L, longitude, 4, 3600);
795 LOGF_INFO(
"Site location updated to Lat %.32s - Long %.32s", l, L);
802 driver->setDebugEnabled(enable);
813 if (TrackState == SCOPE_PARKED)
815 LOG_ERROR(
"Please unpark the mount before issuing any motion commands.");
824 LOG_ERROR(
"Error setting N/S motion direction.");
847 if (TrackState == SCOPE_PARKED)
849 LOG_ERROR(
"Please unpark the mount before issuing any motion commands.");
858 LOG_ERROR(
"Error setting N/S motion direction.");
881 bool rc = driver->startGuide(
IEQ_N, ms);
887 bool rc = driver->startGuide(
IEQ_S, ms);
893 bool rc = driver->startGuide(
IEQ_E, ms);
899 bool rc = driver->startGuide(
IEQ_W, ms);
906 return driver->setSlewRate(rate);
1009 double parkAZ = horizontalCoords.azimuth;
1010 double parkAlt = horizontalCoords.altitude;
1011 char AzStr[16], AltStr[16];
1012 fs_sexa(AzStr, parkAZ, 2, 3600);
1013 fs_sexa(AltStr, parkAlt, 2, 3600);
1014 LOGF_DEBUG(
"Setting current parking position to coordinates Az (%s) Alt (%s)...", AzStr, AltStr);
1015 SetAxis1Park(parkAZ);
1016 SetAxis2Park(parkAlt);
1027 SetAxis2Park(LocationN[LOCATION_LATITUDE].value);
1036 if (driver->setTrackMode(rate))
1044 static bool deRateWarning =
true;
1048 if (deRate != 0 && deRateWarning)
1051 deRateWarning =
false;
1052 LOG_WARN(
"Custom Declination tracking rate is not implemented yet.");
1055 if (driver->setCustomRATrackRate(ieqRARate))
1069 SetTrackRate(TrackRateN[
AXIS_RA].value, TrackRateN[
AXIS_DE].value);
1072 return driver->setTrackEnabled(enabled);
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool Goto(double, double) override
Move the scope to the supplied RA and DEC coordinates.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
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 bool Handshake() override
perform handshake with device to check communication
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
virtual void simulationTriggered(bool enable) override
Inform driver that the simulation option was triggered. This function is called after setSimulation i...
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
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 Abort() override
Abort any telescope motion including tracking if possible.
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool updateTime(ln_date *utc, double utc_offset) override
Update telescope time, date, and UTC offset.
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 ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool SetTrackRate(double raRate, double deRate) override
SetTrackRate Set custom tracking rates.
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
virtual bool Park() override
Park the telescope to its home position.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
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.
The BaseFirmware class provides control for iOptron version 2014 v2.0 protocol.
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.
bool set_ieqpro_dec(int fd, double dec)
bool set_ieqpro_ra(int fd, double ra)
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.
double get_local_sidereal_time(double longitude)
get_local_sidereal_time Returns local sideral time given longitude and system clock.
#define TRACKRATE_SIDEREAL
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 IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
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 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.
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
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 IUGetConfigNumber(const char *dev, const char *property, const char *member, double *value)
IUGetConfigNumber Opens configuration file and reads single number 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,...)
#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...
void EquatorialToHorizontal(IEquatorialCoordinates *object, IGeographicCoordinates *observer, double JD, IHorizontalCoordinates *position)
EquatorialToHorizontal Calculate horizontal coordinates from equatorial coordinates.
void HorizontalToEquatorial(IHorizontalCoordinates *object, IGeographicCoordinates *observer, double JD, IEquatorialCoordinates *position)
HorizontalToEquatorial Calculate Equatorial EOD Coordinates from horizontal coordinates.
const char * getDeviceName()
bool isParked(const int fd)
static Logger & getInstance()
Method to get a reference to the object (i.e., Singleton) It is a static method.
int addDebugLevel(const char *debugLevelName, const char *LoggingLevelName)
Adds a new debugging level to the driver.
SystemStatus systemStatus