Instrument Neutral Distributed Interface INDI  2.0.2
ieqpro.cpp
Go to the documentation of this file.
1 /*
2  INDI IEQ Pro driver
3 
4  Copyright (C) 2015 Jasem Mutlaq
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
21 #include "ieqpro.h"
22 #include "indicom.h"
24 
25 #include <libnova/sidereal_time.h>
26 #include <libnova/transform.h>
27 #include <memory>
28 #include <thread>
29 #include <chrono>
30 
31 #include <cmath>
32 #include <cstring>
33 
34 /* Simulation Parameters */
35 #define SLEWRATE 1 /* slew rate, degrees/s */
36 
37 #define MOUNTINFO_TAB "Mount Info"
38 
39 using namespace iEQ;
40 
41 // We declare an auto pointer to IEQPro.
42 static std::unique_ptr<IEQPro> scope(new IEQPro());
43 
45 {
46  setVersion(1, 9);
47 
48  driver.reset(new Base());
49 
50  scopeInfo.gpsStatus = GPS_OFF;
51  scopeInfo.systemStatus = ST_STOPPED;
52  scopeInfo.trackRate = TR_SIDEREAL;
53  scopeInfo.slewRate = SR_1;
54  scopeInfo.timeSource = TS_RS232;
55  scopeInfo.hemisphere = HEMI_NORTH;
56 
57  DBG_SCOPE = INDI::Logger::getInstance().addDebugLevel("Scope Verbose", "SCOPE");
58 
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,
62  9);
63 }
64 
66 {
67  return "iEQ";
68 }
69 
71 {
73 
74  /* Firmware */
75  IUFillText(&FirmwareT[FW_MODEL], "Model", "", nullptr);
76  IUFillText(&FirmwareT[FW_BOARD], "Board", "", nullptr);
77  IUFillText(&FirmwareT[FW_CONTROLLER], "Controller", "", nullptr);
78  IUFillText(&FirmwareT[FW_RA], "RA", "", nullptr);
79  IUFillText(&FirmwareT[FW_DEC], "DEC", "", nullptr);
80  IUFillTextVector(&FirmwareTP, FirmwareT, 5, getDeviceName(), "Firmware Info", "", MOUNTINFO_TAB, IP_RO, 0,
81  IPS_IDLE);
82 
83  /* Tracking Mode */
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");
89 
90  // Slew Rates
91  strncpy(SlewRateS[0].label, "1x", MAXINDILABEL);
92  strncpy(SlewRateS[1].label, "2x", MAXINDILABEL);
93  strncpy(SlewRateS[2].label, "8x", MAXINDILABEL);
94  strncpy(SlewRateS[3].label, "16x", MAXINDILABEL);
95  strncpy(SlewRateS[4].label, "64x", MAXINDILABEL);
96  strncpy(SlewRateS[5].label, "128x", MAXINDILABEL);
97  strncpy(SlewRateS[6].label, "256x", MAXINDILABEL);
98  strncpy(SlewRateS[7].label, "512x", MAXINDILABEL);
99  strncpy(SlewRateS[8].label, "MAX", MAXINDILABEL);
100  IUResetSwitch(&SlewRateSP);
101  // 64x is the default
102  SlewRateS[4].s = ISS_ON;
103 
104  // Set TrackRate limits within +/- 0.0100 of Sidereal rate
105  TrackRateN[AXIS_RA].min = TRACKRATE_SIDEREAL - 0.01;
106  TrackRateN[AXIS_RA].max = TRACKRATE_SIDEREAL + 0.01;
107  TrackRateN[AXIS_DE].min = -0.01;
108  TrackRateN[AXIS_DE].max = 0.01;
109 
110  /* GPS Status */
111  IUFillSwitch(&GPSStatusS[GPS_OFF], "Off", "", ISS_ON);
112  IUFillSwitch(&GPSStatusS[GPS_ON], "On", "", ISS_OFF);
113  IUFillSwitch(&GPSStatusS[GPS_DATA_OK], "Data OK", "", ISS_OFF);
114  IUFillSwitchVector(&GPSStatusSP, GPSStatusS, 3, getDeviceName(), "GPS_STATUS", "GPS", MOUNTINFO_TAB, IP_RO,
115  ISR_1OFMANY, 0, IPS_IDLE);
116 
117  /* Time Source */
118  IUFillSwitch(&TimeSourceS[TS_RS232], "RS232", "", ISS_ON);
119  IUFillSwitch(&TimeSourceS[TS_CONTROLLER], "Controller", "", ISS_OFF);
120  IUFillSwitch(&TimeSourceS[TS_GPS], "GPS", "", ISS_OFF);
121  IUFillSwitchVector(&TimeSourceSP, TimeSourceS, 3, getDeviceName(), "TIME_SOURCE", "Time Source", MOUNTINFO_TAB,
122  IP_RO, ISR_1OFMANY, 0, IPS_IDLE);
123 
124  /* Hemisphere */
125  IUFillSwitch(&HemisphereS[HEMI_SOUTH], "South", "", ISS_OFF);
126  IUFillSwitch(&HemisphereS[HEMI_NORTH], "North", "", ISS_ON);
127  IUFillSwitchVector(&HemisphereSP, HemisphereS, 2, getDeviceName(), "HEMISPHERE", "Hemisphere", MOUNTINFO_TAB, IP_RO,
128  ISR_1OFMANY, 0, IPS_IDLE);
129 
130  /* Home */
131  IUFillSwitch(&HomeS[IEQ_SET_HOME], "IEQ_SET_HOME", "Set current as Home", ISS_OFF);
132  IUFillSwitch(&HomeS[IEQ_GOTO_HOME], "IEQ_GOTO_HOME", "Go to Home", ISS_OFF);
133  IUFillSwitch(&HomeS[IEQ_FIND_HOME], "IEQ_FIND_HOME", "Find Home", ISS_OFF);
134  IUFillSwitchVector(&HomeSP, HomeS, 3, getDeviceName(), "HOME", "Home", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 0,
135  IPS_IDLE);
136 
137  /* How fast do we guide compared to sidereal rate */
138  IUFillNumber(&GuideRateN[RA_AXIS], "RA_GUIDE_RATE", "RA", "%.2f", 0.01, 0.9, 0.1, 0.5);
139  IUFillNumber(&GuideRateN[DEC_AXIS], "DE_GUIDE_RATE", "DE", "%.2f", 0.1, 0.99, 0.1, 0.5);
140  IUFillNumberVector(&GuideRateNP, GuideRateN, 2, getDeviceName(), "GUIDE_RATE", "Guiding Rate", MOTION_TAB, IP_RW, 0,
141  IPS_IDLE);
142 
143  TrackState = SCOPE_IDLE;
144 
145  initGuiderProperties(getDeviceName(), MOTION_TAB);
146 
147  setDriverInterface(getDriverInterface() | GUIDER_INTERFACE);
148 
149  SetParkDataType(PARK_AZ_ALT);
150 
151  addAuxControls();
152 
153  driver->setDeviceName(getDeviceName());
154 
155  // Only CEM40 and GEM45 have 115200 baud, rest are 9600
156  if (strstr(getDeviceName(), "CEM40") || strstr(getDeviceName(), "GEM45"))
157  serialConnection->setDefaultBaudRate(Connection::Serial::B_115200);
158 
159  currentRA = get_local_sidereal_time(LocationN[LOCATION_LONGITUDE].value);
160  currentDEC = LocationN[LOCATION_LATITUDE].value > 0 ? 90 : -90;
161  return true;
162 }
163 
165 {
166 
167  if (isConnected())
168  {
169  getStartupData();
170 
172 
173  // Remove find home if we do not support it.
174  if (!canFindHome)
175  HomeSP.nsp = 2;
176 
177  defineProperty(&HomeSP);
178 
179  defineProperty(&GuideNSNP);
180  defineProperty(&GuideWENP);
181 
182  if (canGuideRate)
183  defineProperty(&GuideRateNP);
184 
185  defineProperty(&FirmwareTP);
186  defineProperty(&GPSStatusSP);
187  defineProperty(&TimeSourceSP);
188  defineProperty(&HemisphereSP);
189  }
190  else
191  {
193 
194  HomeSP.nsp = 3;
195  deleteProperty(HomeSP.name);
196 
197  deleteProperty(GuideNSNP.name);
198  deleteProperty(GuideWENP.name);
199 
200  if (canGuideRate)
201  deleteProperty(GuideRateNP.name);
202 
203  deleteProperty(FirmwareTP.name);
204  deleteProperty(GPSStatusSP.name);
205  deleteProperty(TimeSourceSP.name);
206  deleteProperty(HemisphereSP.name);
207  }
208 
209  return true;
210 }
211 
212 void IEQPro::getStartupData()
213 {
214  LOG_DEBUG("Getting firmware data...");
215 
216  firmwareInfo = driver->getFirmwareInfo();
217 
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());
223 
224  FirmwareTP.s = IPS_OK;
225  IDSetText(&FirmwareTP, nullptr);
226 
227 
228  LOG_DEBUG("Getting guiding rate...");
229  double raGuideRate = 0, deGuideRate = 0;
230  if (driver->getGuideRate(&raGuideRate, &deGuideRate))
231  {
232  GuideRateN[RA_AXIS].value = raGuideRate;
233  GuideRateN[DEC_AXIS].value = deGuideRate;
234  IDSetNumber(&GuideRateNP, nullptr);
235  }
236 
237  double utc_offset;
238  int yy, dd, mm, hh, minute, ss;
239  if (driver->getUTCDateTime(&utc_offset, &yy, &mm, &dd, &hh, &minute, &ss))
240  {
241  char isoDateTime[32] = {0};
242  char utcOffset[8] = {0};
243 
244  snprintf(isoDateTime, 32, "%04d-%02d-%02dT%02d:%02d:%02d", yy, mm, dd, hh, minute, ss);
245  snprintf(utcOffset, 8, "%4.2f", utc_offset);
246 
247  IUSaveText(IUFindText(&TimeTP, "UTC"), isoDateTime);
248  IUSaveText(IUFindText(&TimeTP, "OFFSET"), utcOffset);
249 
250  LOGF_INFO("Mount UTC offset is %s. UTC time is %s", utcOffset, isoDateTime);
251 
252  TimeTP.s = IPS_OK;
253  IDSetText(&TimeTP, nullptr);
254  }
255 
256  // Get Longitude and Latitude from mount
257  double longitude = 0, latitude = 0;
258  if (driver->getStatus(&scopeInfo))
259  {
260  longitude = scopeInfo.longitude;
261  latitude = scopeInfo.latitude;
262 
263  // Convert to INDI standard longitude (0 to 360 Eastward)
264  if (longitude < 0)
265  longitude += 360;
266 
267  LOGF_INFO("Mount Longitude %g Latitude %g", longitude, latitude);
268 
269  LocationN[LOCATION_LATITUDE].value = latitude;
270  LocationN[LOCATION_LONGITUDE].value = longitude;
271  LocationNP.s = IPS_OK;
272 
273  IDSetNumber(&LocationNP, nullptr);
274 
275  saveConfig(true, "GEOGRAPHIC_COORD");
276  }
277  else if (IUGetConfigNumber(getDeviceName(), "GEOGRAPHIC_COORD", "LONG", &longitude) == 0 &&
278  IUGetConfigNumber(getDeviceName(), "GEOGRAPHIC_COORD", "LAT", &latitude) == 0)
279  {
280  LocationN[LOCATION_LATITUDE].value = latitude;
281  LocationN[LOCATION_LONGITUDE].value = longitude;
282  LocationNP.s = IPS_OK;
283 
284  IDSetNumber(&LocationNP, nullptr);
285  }
286 
287  if (InitPark())
288  {
289  // If loading parking data is successful, we just set the default parking values.
290  SetAxis1ParkDefault(LocationN[LOCATION_LATITUDE].value >= 0 ? 0 : 180);
291  SetAxis2ParkDefault(LocationN[LOCATION_LATITUDE].value);
292  }
293  else
294  {
295  // Otherwise, we set all parking data to default in case no parking data is found.
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);
300  }
301 
302  // can we read pier side?
303  IEQ_PIER_SIDE pierSide = IEQ_PIER_UNKNOWN;
304  if (driver->getPierSide(&pierSide) && pierSide != IEQ_PIER_UNKNOWN)
305  {
306  // add the pier side capability
307  auto cap = GetTelescopeCapability();
308  cap |= TELESCOPE_HAS_PIER_SIDE;
309  SetTelescopeCapability(cap, 9);
310  }
311 
312  // if (isSimulation())
313  // {
314  // if (isParked())
315  // set_sim_system_status(ST_PARKED);
316  // else
317  // set_sim_system_status(ST_STOPPED);
318  // }
319 }
320 
321 bool IEQPro::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
322 {
323  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
324  {
325  // Guiding Rate
326  if (!strcmp(name, GuideRateNP.name))
327  {
328  IUUpdateNumber(&GuideRateNP, values, names, n);
329 
330  if (driver->setGuideRate(GuideRateN[RA_AXIS].value, GuideRateN[DEC_AXIS].value))
331  GuideRateNP.s = IPS_OK;
332  else
333  GuideRateNP.s = IPS_ALERT;
334 
335  IDSetNumber(&GuideRateNP, nullptr);
336 
337  return true;
338  }
339 
340  if (!strcmp(name, GuideNSNP.name) || !strcmp(name, GuideWENP.name))
341  {
342  processGuiderProperties(name, values, names, n);
343  return true;
344  }
345  }
346 
347  return INDI::Telescope::ISNewNumber(dev, name, values, names, n);
348 }
349 
350 bool IEQPro::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
351 {
352  if (!strcmp(getDeviceName(), dev))
353  {
354  if (!strcmp(name, HomeSP.name))
355  {
356  IUUpdateSwitch(&HomeSP, states, names, n);
357 
358  HomeOperation operation = static_cast<HomeOperation>(IUFindOnSwitchIndex(&HomeSP));
359 
360  IUResetSwitch(&HomeSP);
361 
362  switch (operation)
363  {
364  case IEQ_SET_HOME:
365  if (driver->setCurrentHome() == false)
366  {
367  HomeSP.s = IPS_ALERT;
368  IDSetSwitch(&HomeSP, nullptr);
369  return false;
370  }
371 
372  HomeSP.s = IPS_OK;
373  IDSetSwitch(&HomeSP, nullptr);
374  LOG_INFO("Home position set to current coordinates.");
375  return true;
376 
377  case IEQ_GOTO_HOME:
378  if (TrackState == SCOPE_PARKED)
379  {
380  LOG_ERROR("Please unpark the mount before issuing any motion commands.");
381  return false;
382  }
383 
384  if (driver->gotoHome() == false)
385  {
386  HomeSP.s = IPS_ALERT;
387  IDSetSwitch(&HomeSP, nullptr);
388  return false;
389  }
390 
391  HomeSP.s = IPS_OK;
392  IDSetSwitch(&HomeSP, nullptr);
393  LOG_INFO("Slewing to home position...");
394  return true;
395 
396  case IEQ_FIND_HOME:
397  if (driver->findHome() == false)
398  {
399  HomeSP.s = IPS_ALERT;
400  IDSetSwitch(&HomeSP, nullptr);
401  return false;
402  }
403 
404  HomeSP.s = IPS_OK;
405  IDSetSwitch(&HomeSP, nullptr);
406  LOG_INFO("Searching for home position...");
407  return true;
408  }
409 
410  return true;
411  }
412  }
413 
414  return INDI::Telescope::ISNewSwitch(dev, name, states, names, n);
415 }
416 
418 {
419  iEQ::Base::Info newInfo;
420 
421  // if (isSimulation())
422  // mountSim();
423 
424  bool rc = driver->getStatus(&newInfo);
425 
426  if (rc)
427  {
428  IUResetSwitch(&GPSStatusSP);
429  GPSStatusS[newInfo.gpsStatus].s = ISS_ON;
430  IDSetSwitch(&GPSStatusSP, nullptr);
431 
432  IUResetSwitch(&TimeSourceSP);
433  TimeSourceS[newInfo.timeSource].s = ISS_ON;
434  IDSetSwitch(&TimeSourceSP, nullptr);
435 
436  IUResetSwitch(&HemisphereSP);
437  HemisphereS[newInfo.hemisphere].s = ISS_ON;
438  IDSetSwitch(&HemisphereSP, nullptr);
439 
440  /*
441  TelescopeTrackMode trackMode = TRACK_SIDEREAL;
442 
443  switch (newInfo.trackRate)
444  {
445  case TR_SIDEREAL:
446  trackMode = TRACK_SIDEREAL;
447  break;
448  case TR_SOLAR:
449  trackMode = TRACK_SOLAR;
450  break;
451  case TR_LUNAR:
452  trackMode = TRACK_LUNAR;
453  break;
454  case TR_KING:
455  trackMode = TRACK_SIDEREAL;
456  break;
457  case TR_CUSTOM:
458  trackMode = TRACK_CUSTOM;
459  break;
460  }*/
461 
462  switch (newInfo.systemStatus)
463  {
464  case ST_STOPPED:
465  TrackModeSP.s = IPS_IDLE;
466  // If we cannot park natively and we already parked
467  // scope, we do not want its state to change to IDLE
468  // For scopes that can park natively, ST_PARKED would be
469  // set already.
470  if (canParkNatively || TrackState != SCOPE_PARKED)
471  TrackState = SCOPE_IDLE;
472  break;
473  case ST_PARKED:
474  TrackModeSP.s = IPS_IDLE;
475  TrackState = SCOPE_PARKED;
476  if (!isParked())
477  SetParked(true);
478  break;
479  case ST_HOME:
480  TrackModeSP.s = IPS_IDLE;
481  TrackState = SCOPE_IDLE;
482  break;
483  case ST_SLEWING:
485  slewDirty = true;
486  if (TrackState != SCOPE_SLEWING && TrackState != SCOPE_PARKING)
487  TrackState = SCOPE_SLEWING;
488  break;
489  case ST_TRACKING_PEC_OFF:
490  case ST_TRACKING_PEC_ON:
491  case ST_GUIDING:
492  if (TrackState == SCOPE_PARKING && canParkNatively == false)
493  {
494  if (slewDirty)
495  {
496  LOG_INFO("Manual parking complete. Shut the mount down.");
497  TrackModeSP.s = IPS_IDLE;
498  TrackState = SCOPE_PARKED;
499  SetTrackEnabled(false);
500  SetParked(true);
501  slewDirty = false;
502  }
503  }
504  else
505  {
506  TrackModeSP.s = IPS_BUSY;
507  TrackState = SCOPE_TRACKING;
508  if (scopeInfo.systemStatus == ST_SLEWING)
509  LOG_INFO("Slew complete, tracking...");
510  else if (scopeInfo.systemStatus == ST_MERIDIAN_FLIPPING)
511  LOG_INFO("Meridian flip complete, tracking...");
512  }
513  break;
514  }
515 
516  IUResetSwitch(&TrackModeSP);
517  TrackModeS[newInfo.trackRate].s = ISS_ON;
518  IDSetSwitch(&TrackModeSP, nullptr);
519 
520  scopeInfo = newInfo;
521  }
522 
523  if (HasPierSide())
524  {
525  IEQ_PIER_SIDE pierSide;
526  if (driver->getPierSide(&pierSide))
527  {
528  TelescopePierSide tps = PIER_UNKNOWN;
529  switch (pierSide)
530  {
531  case IEQ_PIER_UNKNOWN:
532  case IEQ_PIER_UNCERTAIN:
533  tps = PIER_UNKNOWN;
534  break;
535  case IEQ_PIER_EAST:
536  tps = PIER_EAST;
537  break;
538  case IEQ_PIER_WEST:
539  tps = PIER_WEST;
540  break;
541  }
542  setPierSide(tps);
543  }
544  }
545 
546  rc = driver->getCoords(&currentRA, &currentDEC);
547 
548  if (rc)
549  NewRaDec(currentRA, currentDEC);
550 
551  return rc;
552 }
553 
554 bool IEQPro::Goto(double r, double d)
555 {
556  targetRA = r;
557  targetDEC = d;
558  char RAStr[64] = {0}, DecStr[64] = {0};
559 
560  fs_sexa(RAStr, targetRA, 2, 3600);
561  fs_sexa(DecStr, targetDEC, 2, 3600);
562 
563  if (driver->setRA(r) == false || driver->setDE(d) == false)
564  {
565  LOG_ERROR("Error setting RA/DEC.");
566  return false;
567  }
568 
569  if (driver->slew() == false)
570  {
571  LOG_ERROR("Failed to slew.");
572  return false;
573  }
574 
575  iEQ::Base::Info newInfo;
576 
577  // Wait until the mount system status changes to SLEWING
578  // up to 500ms
579  for (int i = 0; i < 5; i++)
580  {
581  bool rc = driver->getStatus(&newInfo);
582  if (rc && newInfo.systemStatus == ST_SLEWING)
583  break;
584  std::this_thread::sleep_for(std::chrono::milliseconds(100));
585  }
586 
587  if (newInfo.systemStatus == ST_SLEWING)
588  {
589  TrackState = SCOPE_SLEWING;
590  LOGF_INFO("Slewing to RA: %s - DEC: %s", RAStr, DecStr);
591  return true;
592  }
593  else
594  {
595  LOG_ERROR("Mount status failed to update to slewing.");
596  return false;
597  }
598 }
599 
600 bool IEQPro::Sync(double ra, double dec)
601 {
602  if (driver->setRA(ra) == false || driver->setDE(dec) == false)
603  {
604  LOG_ERROR("Error setting RA/DEC.");
605  return false;
606  }
607 
608  if (driver->sync() == false)
609  {
610  LOG_ERROR("Failed to sync.");
611  }
612 
613  EqNP.s = IPS_OK;
614 
615  currentRA = ra;
616  currentDEC = dec;
617 
618  NewRaDec(currentRA, currentDEC);
619 
620  return true;
621 }
622 
624 {
625  return driver->abort();
626 }
627 
629 {
630 #if 0
631  targetRA = GetAxis1Park();
632  targetDEC = GetAxis2Park();
633 
634  if (set_ieqpro_ra(PortFD, targetRA) == false || set_ieqpro_dec(PortFD, targetDEC) == false)
635  {
636  LOG_ERROR("Error setting RA/DEC.");
637  return false;
638  }
639 
640  if (slew_ieqpro(PortFD) == false)
641  {
642  LOG_ERROR("Failed to slew tp parking position.");
643  return false;
644  }
645 
646  char RAStr[64] = {0}, DecStr[64] = {0};
647  fs_sexa(RAStr, targetRA, 2, 3600);
648  fs_sexa(DecStr, targetDEC, 2, 3600);
649 
650  TrackState = SCOPE_PARKING;
651  LOGF_INFO("Telescope parking in progress to RA: %s DEC: %s", RAStr, DecStr);
652 
653  return true;
654 #endif
655 
656  double parkAz = GetAxis1Park();
657  double parkAlt = GetAxis2Park();
658 
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);
663 
664  // Check if mount supports native Alt/Az parking
665  if (canParkNatively)
666  {
667  if (driver->setParkAz(parkAz) && driver->setParkAlt(parkAlt))
668  {
669  if (driver->park())
670  {
671  TrackState = SCOPE_PARKING;
672  LOG_INFO("Parking is in progress...");
673  return true;
674  }
675  else
676  return false;
677  }
678  else
679  return false;
680  }
681 
682  // Otherwise fallback to Alt/Az --> RA/DE parking
683  INDI::IHorizontalCoordinates horizontalPos;
684  horizontalPos.azimuth = parkAz;
685  horizontalPos.altitude = parkAlt;
686  INDI::IEquatorialCoordinates equatorialPos;
687 
688  INDI::HorizontalToEquatorial(&horizontalPos, &m_Location, ln_get_julian_from_sys(), &equatorialPos);
689 
690  if (Goto(equatorialPos.rightascension, equatorialPos.declination))
691  {
692  TrackState = SCOPE_PARKING;
693  LOG_INFO("Parking is in progress...");
694 
695  slewDirty = false;
696  return true;
697  }
698  else
699  return false;
700 }
701 
703 {
704  // If we can park natively, let's try to unpark the mount first.
705  // If that fails, we return. Otherwise, we proceed even when
706  // we are manually unparking.
707  if (canParkNatively && driver->unpark() == false)
708  return false;
709 
710  SetParked(false);
711  TrackState = SCOPE_IDLE;
712  return true;
713 }
714 
716 {
717  // if (isSimulation())
718  // {
719  // set_sim_gps_status(GPS_DATA_OK);
720  // set_sim_system_status(ST_STOPPED);
721  // set_sim_track_rate(TR_SIDEREAL);
722  // set_sim_slew_rate(SR_3);
723  // set_sim_time_source(TS_GPS);
724  // set_sim_hemisphere(HEMI_NORTH);
725  // }
726 
727  if (driver->initCommunication(PortFD) == false)
728  return false;
729 
730  canParkNatively = driver->isCommandSupported("MP1", true);
731  canFindHome = driver->isCommandSupported("MSH", true);
732  canGuideRate = driver->isCommandSupported("RG", true);
733 
734  return true;
735 }
736 
737 bool IEQPro::updateTime(ln_date *utc, double utc_offset)
738 {
739  struct ln_zonedate ltm;
740 
741  ln_date_to_zonedate(utc, &ltm, utc_offset * 3600.0);
742 
743  // Set Local Time
744  if (driver->setLocalTime(ltm.hours, ltm.minutes, ltm.seconds) == false)
745  {
746  LOG_ERROR("Error setting local time.");
747  return false;
748  }
749 
750  // Send it as YY (i.e. 2015 --> 15)
751  ltm.years -= 2000;
752 
753  // Set Local date
754  if (driver->setLocalDate(ltm.years, ltm.months, ltm.days) == false)
755  {
756  LOG_ERROR("Error setting local date.");
757  return false;
758  }
759 
760  // UTC Offset
761  if (driver->setUTCOffset(utc_offset) == false)
762  {
763  LOG_ERROR("Error setting UTC Offset.");
764  return false;
765  }
766 
767  LOG_INFO("Time and date updated.");
768 
769  return true;
770 }
771 
772 bool IEQPro::updateLocation(double latitude, double longitude, double elevation)
773 {
774  INDI_UNUSED(elevation);
775 
776  if (longitude > 180)
777  longitude -= 360;
778 
779  if (driver->setLongitude(longitude) == false)
780  {
781  LOG_ERROR("Failed to set longitude.");
782  return false;
783  }
784 
785  if (driver->setLatitude(latitude) == false)
786  {
787  LOG_ERROR("Failed to set latitude.");
788  return false;
789  }
790 
791  char l[32] = {0}, L[32] = {0};
792  fs_sexa(l, latitude, 3, 3600);
793  fs_sexa(L, longitude, 4, 3600);
794 
795  LOGF_INFO("Site location updated to Lat %.32s - Long %.32s", l, L);
796 
797  return true;
798 }
799 
800 void IEQPro::debugTriggered(bool enable)
801 {
802  driver->setDebugEnabled(enable);
803 }
804 
806 {
807  INDI_UNUSED(enable);
808  //driver->setSi(enable);
809 }
810 
812 {
813  if (TrackState == SCOPE_PARKED)
814  {
815  LOG_ERROR("Please unpark the mount before issuing any motion commands.");
816  return false;
817  }
818 
819  switch (command)
820  {
821  case MOTION_START:
822  if (driver->startMotion((dir == DIRECTION_NORTH ? IEQ_N : IEQ_S)) == false)
823  {
824  LOG_ERROR("Error setting N/S motion direction.");
825  return false;
826  }
827  else
828  LOGF_INFO("Moving toward %s.", (dir == DIRECTION_NORTH) ? "North" : "South");
829  break;
830 
831  case MOTION_STOP:
832  if (driver->stopMotion((dir == DIRECTION_NORTH ? IEQ_N : IEQ_S)) == false)
833  {
834  LOG_ERROR("Error stopping N/S motion.");
835  return false;
836  }
837  else
838  LOGF_INFO("%s motion stopped.", (dir == DIRECTION_NORTH) ? "North" : "South");
839  break;
840  }
841 
842  return true;
843 }
844 
846 {
847  if (TrackState == SCOPE_PARKED)
848  {
849  LOG_ERROR("Please unpark the mount before issuing any motion commands.");
850  return false;
851  }
852 
853  switch (command)
854  {
855  case MOTION_START:
856  if (driver->startMotion((dir == DIRECTION_WEST ? IEQ_W : IEQ_E)) == false)
857  {
858  LOG_ERROR("Error setting N/S motion direction.");
859  return false;
860  }
861  else
862  LOGF_INFO("Moving toward %s.", (dir == DIRECTION_WEST) ? "West" : "East");
863  break;
864 
865  case MOTION_STOP:
866  if (driver->stopMotion((dir == DIRECTION_WEST ? IEQ_W : IEQ_E)) == false)
867  {
868  LOG_ERROR("Error stopping W/E motion.");
869  return false;
870  }
871  else
872  LOGF_INFO("%s motion stopped.", (dir == DIRECTION_WEST) ? "West" : "East");
873  break;
874  }
875 
876  return true;
877 }
878 
880 {
881  bool rc = driver->startGuide(IEQ_N, ms);
882  return (rc ? IPS_OK : IPS_ALERT);
883 }
884 
886 {
887  bool rc = driver->startGuide(IEQ_S, ms);
888  return (rc ? IPS_OK : IPS_ALERT);
889 }
890 
892 {
893  bool rc = driver->startGuide(IEQ_E, ms);
894  return (rc ? IPS_OK : IPS_ALERT);
895 }
896 
898 {
899  bool rc = driver->startGuide(IEQ_W, ms);
900  return (rc ? IPS_OK : IPS_ALERT);
901 }
902 
903 bool IEQPro::SetSlewRate(int index)
904 {
905  SlewRate rate = static_cast<SlewRate>(index);
906  return driver->setSlewRate(rate);
907 }
908 
910 {
912 
913  return true;
914 }
915 
916 //void IEQPro::mountSim()
917 //{
918 // static struct timeval ltv;
919 // struct timeval tv;
920 // double dt, da, dx;
921 // int nlocked;
922 
923 // /* update elapsed time since last poll, don't presume exactly POLLMS */
924 // gettimeofday(&tv, nullptr);
925 
926 // if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
927 // ltv = tv;
928 
929 // dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
930 // ltv = tv;
931 // da = SLEWRATE * dt;
932 
933 // /* Process per current state. We check the state of EQUATORIAL_COORDS and act acoordingly */
934 // switch (TrackState)
935 // {
936 // case SCOPE_IDLE:
937 // currentRA += (TrackRateN[AXIS_RA].value / 3600.0 * dt) / 15.0;
938 // currentRA = range24(currentRA);
939 // break;
940 
941 // case SCOPE_TRACKING:
942 // if (TrackModeS[1].s == ISS_ON)
943 // {
944 // currentRA += ( ((TRACKRATE_SIDEREAL / 3600.0) - (TrackRateN[AXIS_RA].value / 3600.0)) * dt) / 15.0;
945 // currentDEC += ( (TrackRateN[AXIS_DE].value / 3600.0) * dt);
946 // }
947 // break;
948 
949 // case SCOPE_SLEWING:
950 // case SCOPE_PARKING:
951 // /* slewing - nail it when both within one pulse @ SLEWRATE */
952 // nlocked = 0;
953 
954 // dx = targetRA - currentRA;
955 
956 // // Take shortest path
957 // if (fabs(dx) > 12)
958 // dx *= -1;
959 
960 // if (fabs(dx) <= da)
961 // {
962 // currentRA = targetRA;
963 // nlocked++;
964 // }
965 // else if (dx > 0)
966 // currentRA += da / 15.;
967 // else
968 // currentRA -= da / 15.;
969 
970 // if (currentRA < 0)
971 // currentRA += 24;
972 // else if (currentRA > 24)
973 // currentRA -= 24;
974 
975 // dx = targetDEC - currentDEC;
976 // if (fabs(dx) <= da)
977 // {
978 // currentDEC = targetDEC;
979 // nlocked++;
980 // }
981 // else if (dx > 0)
982 // currentDEC += da;
983 // else
984 // currentDEC -= da;
985 
986 // if (nlocked == 2)
987 // {
988 // if (TrackState == SCOPE_SLEWING)
989 // set_sim_system_status(ST_TRACKING_PEC_OFF);
990 // else
991 // set_sim_system_status(ST_PARKED);
992 // }
993 
994 // break;
995 
996 // default:
997 // break;
998 // }
999 
1000 // set_sim_ra(currentRA);
1001 // set_sim_dec(currentDEC);
1002 //}
1003 
1005 {
1007  INDI::IHorizontalCoordinates horizontalCoords {0, 0};
1008  INDI::EquatorialToHorizontal(&equatorialCoords, &m_Location, ln_get_julian_from_sys(), &horizontalCoords);
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);
1017 
1018  return true;
1019 }
1020 
1022 {
1023  // By defualt azimuth 0
1024  SetAxis1Park(0);
1025 
1026  // Altitude = latitude of observer
1027  SetAxis2Park(LocationN[LOCATION_LATITUDE].value);
1028 
1029  return true;
1030 }
1031 
1032 bool IEQPro::SetTrackMode(uint8_t mode)
1033 {
1034  TrackRate rate = static_cast<TrackRate>(mode);
1035 
1036  if (driver->setTrackMode(rate))
1037  return true;
1038 
1039  return false;
1040 }
1041 
1042 bool IEQPro::SetTrackRate(double raRate, double deRate)
1043 {
1044  static bool deRateWarning = true;
1045 
1046  // Convert to arcsecs/s to +/- 0.0100 accepted by
1047  double ieqRARate = raRate - TRACKRATE_SIDEREAL;
1048  if (deRate != 0 && deRateWarning)
1049  {
1050  // Only send warning once per session
1051  deRateWarning = false;
1052  LOG_WARN("Custom Declination tracking rate is not implemented yet.");
1053  }
1054 
1055  if (driver->setCustomRATrackRate(ieqRARate))
1056  return true;
1057 
1058  return false;
1059 }
1060 
1061 bool IEQPro::SetTrackEnabled(bool enabled)
1062 {
1063  if (enabled)
1064  {
1065  // If we are engaging tracking, let us first set tracking mode, and if we have custom mode, then tracking rate.
1066  // NOTE: Is this the correct order? or should tracking be switched on first before making these changes? Need to test.
1067  SetTrackMode(IUFindOnSwitchIndex(&TrackModeSP));
1068  if (TrackModeS[TR_CUSTOM].s == ISS_ON)
1069  SetTrackRate(TrackRateN[AXIS_RA].value, TrackRateN[AXIS_DE].value);
1070  }
1071 
1072  return driver->setTrackEnabled(enabled);
1073 }
Definition: ieqpro.h:30
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
Definition: ieqpro.cpp:885
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
Definition: ieqpro.cpp:1061
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: ieqpro.cpp:909
IEQPro()
Definition: ieqpro.cpp:44
virtual bool Goto(double, double) override
Move the scope to the supplied RA and DEC coordinates.
Definition: ieqpro.cpp:554
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition: ieqpro.cpp:70
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
Definition: ieqpro.cpp:600
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
Definition: ieqpro.cpp:879
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
Definition: ieqpro.cpp:1021
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: ieqpro.cpp:164
virtual bool Handshake() override
perform handshake with device to check communication
Definition: ieqpro.cpp:715
virtual bool UnPark() override
Unpark the telescope if already parked.
Definition: ieqpro.cpp:702
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
Definition: ieqpro.cpp:800
virtual void simulationTriggered(bool enable) override
Inform driver that the simulation option was triggered. This function is called after setSimulation i...
Definition: ieqpro.cpp:805
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
Definition: ieqpro.cpp:897
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
Definition: ieqpro.cpp:1004
virtual bool SetSlewRate(int index) override
SetSlewRate Set desired slew rate index.
Definition: ieqpro.cpp:903
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
Definition: ieqpro.cpp:623
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
Definition: ieqpro.cpp:891
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
Definition: ieqpro.cpp:845
virtual bool updateTime(ln_date *utc, double utc_offset) override
Update telescope time, date, and UTC offset.
Definition: ieqpro.cpp:737
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: ieqpro.cpp:321
virtual const char * getDefaultName() override
Definition: ieqpro.cpp:65
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: ieqpro.cpp:350
virtual bool ReadScopeStatus() override
Read telescope status.
Definition: ieqpro.cpp:417
virtual bool SetTrackRate(double raRate, double deRate) override
SetTrackRate Set custom tracking rates.
Definition: ieqpro.cpp:1042
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
Definition: ieqpro.cpp:811
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
Definition: ieqpro.cpp:1032
virtual bool Park() override
Park the telescope to its home position.
Definition: ieqpro.cpp:628
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
Definition: ieqpro.cpp:772
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.
Definition: ieqdriverbase.h:58
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.
#define currentDEC
Definition: ieq45.cpp:48
#define currentRA
Definition: ieq45.cpp:47
#define MOUNTINFO_TAB
Definition: ieqpro.cpp:37
bool slew_ieqpro(int fd)
double ra
bool set_ieqpro_dec(int fd, double dec)
double dec
bool set_ieqpro_ra(int fd, double ra)
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
#define MAXINDILABEL
Definition: indiapi.h:192
@ ISR_1OFMANY
Definition: indiapi.h:173
@ ISR_ATMOST1
Definition: indiapi.h:174
@ AXIS_DE
Definition: indibasetypes.h:36
@ AXIS_RA
Definition: indibasetypes.h:35
INDI_DIR_WE
Definition: indibasetypes.h:55
@ DIRECTION_WEST
Definition: indibasetypes.h:56
INDI_DIR_NS
Definition: indibasetypes.h:48
@ DIRECTION_NORTH
Definition: indibasetypes.h:49
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[].
Definition: indicom.c:141
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
Definition: indicom.h:55
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.
Definition: indidevapi.c:272
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
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.
Definition: indidevapi.c:291
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
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.
Definition: indidevapi.c:158
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.
Definition: indidevapi.c:198
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.
Definition: indidevapi.c:180
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.
Definition: indidevapi.c:235
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition: indidevapi.c:56
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
int IUGetConfigNumber(const char *dev, const char *property, const char *member, double *value)
IUGetConfigNumber Opens configuration file and reads single number property.
Definition: indidriver.c:831
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
#define LOG_WARN(txt)
Definition: indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
#define LOG_INFO(txt)
Definition: indilogger.h:74
unsigned int DBG_SCOPE
Definition: lx200driver.cpp:53
void EquatorialToHorizontal(IEquatorialCoordinates *object, IGeographicCoordinates *observer, double JD, IHorizontalCoordinates *position)
EquatorialToHorizontal Calculate horizontal coordinates from equatorial coordinates.
Definition: libastro.cpp:140
void HorizontalToEquatorial(IHorizontalCoordinates *object, IGeographicCoordinates *observer, double JD, IEquatorialCoordinates *position)
HorizontalToEquatorial Calculate Equatorial EOD Coordinates from horizontal coordinates.
Definition: libastro.cpp:156
const char * getDeviceName()
bool isParked(const int fd)
@ IEQ_E
Definition: ieqdriverbase.h:49
@ IEQ_W
Definition: ieqdriverbase.h:49
@ IEQ_N
Definition: ieqdriverbase.h:49
@ IEQ_S
Definition: ieqdriverbase.h:49
@ TR_SIDEREAL
Definition: ieqdriverbase.h:43
@ TR_CUSTOM
Definition: ieqdriverbase.h:43
@ TS_CONTROLLER
Definition: ieqdriverbase.h:45
@ TS_GPS
Definition: ieqdriverbase.h:45
@ TS_RS232
Definition: ieqdriverbase.h:45
@ SR_1
Definition: ieqdriverbase.h:44
@ FW_MODEL
Definition: ieqdriverbase.h:47
@ FW_BOARD
Definition: ieqdriverbase.h:47
@ FW_RA
Definition: ieqdriverbase.h:47
@ FW_CONTROLLER
Definition: ieqdriverbase.h:47
@ FW_DEC
Definition: ieqdriverbase.h:47
@ GPS_ON
Definition: ieqdriverbase.h:30
@ GPS_OFF
Definition: ieqdriverbase.h:30
@ GPS_DATA_OK
Definition: ieqdriverbase.h:30
@ HEMI_NORTH
Definition: ieqdriverbase.h:46
@ HEMI_SOUTH
Definition: ieqdriverbase.h:46
@ ST_HOME
Definition: ieqdriverbase.h:40
@ ST_SLEWING
Definition: ieqdriverbase.h:35
@ ST_MERIDIAN_FLIPPING
Definition: ieqdriverbase.h:37
@ ST_TRACKING_PEC_OFF
Definition: ieqdriverbase.h:34
@ ST_STOPPED
Definition: ieqdriverbase.h:33
@ ST_TRACKING_PEC_ON
Definition: ieqdriverbase.h:38
@ ST_GUIDING
Definition: ieqdriverbase.h:36
@ ST_PARKED
Definition: ieqdriverbase.h:39
IEQ_PIER_SIDE
Definition: ieqdriverbase.h:52
@ IEQ_PIER_EAST
Definition: ieqdriverbase.h:52
@ IEQ_PIER_WEST
Definition: ieqdriverbase.h:52
@ IEQ_PIER_UNCERTAIN
Definition: ieqdriverbase.h:52
@ IEQ_PIER_UNKNOWN
Definition: ieqdriverbase.h:52
@ DEC_AXIS
Definition: ieqdriverbase.h:48
@ RA_AXIS
Definition: ieqdriverbase.h:48
HomeOperation
Definition: ieqdriverbase.h:50
@ IEQ_GOTO_HOME
Definition: ieqdriverbase.h:50
@ IEQ_FIND_HOME
Definition: ieqdriverbase.h:50
@ IEQ_SET_HOME
Definition: ieqdriverbase.h:50
static Logger & getInstance()
Method to get a reference to the object (i.e., Singleton) It is a static method.
Definition: indilogger.cpp:339
int addDebugLevel(const char *debugLevelName, const char *LoggingLevelName)
Adds a new debugging level to the driver.
Definition: indilogger.cpp:72
TrackRate trackRate
Definition: ieqdriverbase.h:69
SystemStatus systemStatus
Definition: ieqdriverbase.h:67
TimeSource timeSource
Definition: ieqdriverbase.h:71
Hemisphere hemisphere
Definition: ieqdriverbase.h:72
GPSStatus gpsStatus
Definition: ieqdriverbase.h:66