Instrument Neutral Distributed Interface INDI  1.9.5
lx200telescope.cpp
Go to the documentation of this file.
1 /*
2  * Standard LX200 implementation.
3 
4  Copyright (C) 2003 - 2018 Jasem Mutlaq (mutlaqja@ikarustech.com)
5  Minor changes Copyright (C) 2021 James Lancaster
6 
7  This library is free software;
8  you can redistribute it and / or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation;
11  either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY;
16  without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public
21  License along with this library;
22  if not, write to the Free Software
23  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA
24  */
25 
26 #include "lx200telescope.h"
27 
28 #include "indicom.h"
29 #include "lx200driver.h"
30 
31 #include <libnova/sidereal_time.h>
32 
33 #include <cmath>
34 #include <memory>
35 #include <cstring>
36 #include <unistd.h>
37 #include <time.h>
38 
39 /* Simulation Parameters */
40 #define LX200_GENERIC_SLEWRATE 5 /* slew rate, degrees/s */
41 #define SIDRATE 0.004178 /* sidereal rate, degrees/s */
42 
44 {
45 }
46 
48 {
49  INDI_UNUSED(enable);
51 }
52 
54 {
55  return getDefaultName();
56 }
57 
59 {
60  return static_cast<const char *>("Standard LX200");
61 }
62 
63 
65 {
66  /* Make sure to init parent properties first */
68 
69  IUFillSwitch(&AlignmentS[0], "Polar", "", ISS_ON);
70  IUFillSwitch(&AlignmentS[1], "AltAz", "", ISS_OFF);
71  IUFillSwitch(&AlignmentS[2], "Land", "", ISS_OFF);
73  ISR_1OFMANY, 0, IPS_IDLE);
74 
75 #if 0
76  IUFillSwitch(&SlewRateS[SLEW_GUIDE], "SLEW_GUIDE", "Guide", ISS_OFF);
77  IUFillSwitch(&SlewRateS[SLEW_CENTERING], "SLEW_CENTERING", "Centering", ISS_OFF);
78  IUFillSwitch(&SlewRateS[SLEW_FIND], "SLEW_FIND", "Find", ISS_OFF);
79  IUFillSwitch(&SlewRateS[SLEW_MAX], "SLEW_MAX", "Max", ISS_ON);
80  IUFillSwitchVector(&SlewRateSP, SlewRateS, 4, getDeviceName(), "TELESCOPE_SLEW_RATE", "Slew Rate", MOTION_TAB, IP_RW,
81  ISR_1OFMANY, 0, IPS_IDLE);
82 #endif
83 
84 #if 0
85  IUFillSwitch(&TrackModeS[0], "TRACK_SIDEREAL", "Sidereal", ISS_ON);
86  IUFillSwitch(&TrackModeS[1], "TRACK_SOLAR", "Solar", ISS_OFF);
87  IUFillSwitch(&TrackModeS[2], "TRACK_LUNAR", "Lunar", ISS_OFF);
88  IUFillSwitch(&TrackModeS[3], "TRACK_CUSTOM", "Custom", ISS_OFF);
89  IUFillSwitchVector(&TrackModeSP, TrackModeS, 4, getDeviceName(), "TELESCOPE_TRACK_MODE", "Track Mode", MOTION_TAB,
91 #endif
92 
93  AddTrackMode("TRACK_SIDEREAL", "Sidereal", true);
94  AddTrackMode("TRACK_SOLAR", "Solar");
95  AddTrackMode("TRACK_LUNAR", "Lunar");
96  AddTrackMode("TRACK_CUSTOM", "Custom");
97 
99  {
100  IUFillNumber(&TrackFreqN[0], "trackFreq", "Freq", "%g", 55, 65, 0.00001, 60.16427);
101  }
102  else
103  {
104  IUFillNumber(&TrackFreqN[0], "trackFreq", "Freq", "%g", 56.4, 60.1, 0.1, 60.1);
105  }
106  IUFillNumberVector(&TrackFreqNP, TrackFreqN, 1, getDeviceName(), "Tracking Frequency", "", MOTION_TAB, IP_RW, 0,
107  IPS_IDLE);
108 
109  IUFillSwitch(&UsePulseCmdS[0], "Off", "Off", ISS_OFF);
110  IUFillSwitch(&UsePulseCmdS[1], "On", "On", ISS_ON);
112  ISR_1OFMANY, 0, IPS_IDLE);
113 
114  int selectedSite = 0;
115  IUGetConfigOnSwitchIndex(getDeviceName(), "Sites", &selectedSite);
116  IUFillSwitch(&SiteS[0], "Site 1", "Site 1", selectedSite == 0 ? ISS_ON : ISS_OFF);
117  IUFillSwitch(&SiteS[1], "Site 2", "Site 2", selectedSite == 1 ? ISS_ON : ISS_OFF);
118  IUFillSwitch(&SiteS[2], "Site 3", "Site 3", selectedSite == 2 ? ISS_ON : ISS_OFF);
119  IUFillSwitch(&SiteS[3], "Site 4", "Site 4", selectedSite == 3 ? ISS_ON : ISS_OFF);
121 
122  char siteName[64] = {"NA"};
123  IUGetConfigText(getDeviceName(), "Site Name", "Name", siteName, 64);
124  IUFillText(&SiteNameT[0], "Name", "Name", siteName);
125  IUFillTextVector(&SiteNameTP, SiteNameT, 1, getDeviceName(), "Site Name", "Site Name", SITE_TAB, IP_RW, 0, IPS_IDLE);
126 
127 
129  {
132 
133  // IUFillSwitch(&FocusModeS[0], "FOCUS_HALT", "Halt", ISS_ON);
134  // IUFillSwitch(&FocusModeS[1], "FOCUS_SLOW", "Slow", ISS_OFF);
135  // IUFillSwitch(&FocusModeS[2], "FOCUS_FAST", "Fast", ISS_OFF);
136  // IUFillSwitchVector(&FocusModeSP, FocusModeS, 3, getDeviceName(), "FOCUS_MODE", "Mode", FOCUS_TAB, IP_RW,
137  // ISR_1OFMANY, 0, IPS_IDLE);
138 
139  // Classical speeds slow or fast
140  FocusSpeedN[0].min = 1;
141  FocusSpeedN[0].max = 2;
142  FocusSpeedN[0].value = 1;
143  }
144 
146 
148 
149  /* Add debug/simulation/config controls so we may debug driver if necessary */
150  addAuxControls();
151 
153 
154  if (m_Location.longitude > 0)
156  if (m_Location.latitude != 0)
157  currentDEC = m_Location.latitude > 0 ? 90 : -90;
158  return true;
159 }
160 
161 void LX200Telescope::ISGetProperties(const char *dev)
162 {
163  if (dev != nullptr && strcmp(dev, getDeviceName()) != 0)
164  return;
165 
167 
168  /*
169  if (isConnected())
170  {
171  if (genericCapability & LX200_HAS_ALIGNMENT_TYPE)
172  defineProperty(&AlignmentSP);
173 
174  if (genericCapability & LX200_HAS_TRACKING_FREQ)
175  defineProperty(&TrackFreqNP);
176 
177  if (genericCapability & LX200_HAS_PULSE_GUIDING)
178  defineProperty(&UsePulseCmdSP);
179 
180  if (genericCapability & LX200_HAS_SITES)
181  {
182  defineProperty(&SiteSP);
183  defineProperty(&SiteNameTP);
184  }
185 
186  defineProperty(&GuideNSNP);
187  defineProperty(&GuideWENP);
188 
189  if (genericCapability & LX200_HAS_FOCUS)
190  {
191  defineProperty(&FocusMotionSP);
192  defineProperty(&FocusTimerNP);
193  defineProperty(&FocusModeSP);
194  }
195  }
196  */
197 }
198 
200 {
202 
203  if (isConnected())
204  {
207 
210 
213 
215  {
218  }
219 
222 
224  {
226  //defineProperty(&FocusModeSP);
227  }
228 
229  getBasicData();
230  }
231  else
232  {
235 
238 
241 
243  {
246  }
247 
250 
252  {
254  //deleteProperty(FocusModeSP.name);
255  }
256  }
257 
258  return true;
259 }
260 
262 {
263  if (isSimulation())
264  return true;
265 
266  return (check_lx200_connection(PortFD) == 0);
267 }
268 
270 {
271  return checkConnection();
272 }
273 
275 {
276  return (::isSlewComplete(PortFD) == 1);
277 }
278 
280 {
281  if (!isConnected())
282  return false;
283 
284  if (isSimulation())
285  {
286  mountSim();
287  return true;
288  }
289 
290  //if (check_lx200_connection(PortFD))
291  //return false;
292 
293  if (TrackState == SCOPE_SLEWING)
294  {
295  // Check if LX200 is done slewing
296  if (isSlewComplete())
297  {
298  // Set slew mode to "Centering"
301  IDSetSwitch(&SlewRateSP, nullptr);
302 
304  LOG_INFO("Slew is complete. Tracking...");
305  }
306  }
307  else if (TrackState == SCOPE_PARKING)
308  {
309  if (isSlewComplete())
310  {
311  SetParked(true);
312  }
313  }
314 
316  {
317  EqNP.s = IPS_ALERT;
318  IDSetNumber(&EqNP, "Error reading RA/DEC.");
319  return false;
320  }
321 
323 
324  return true;
325 }
326 
327 bool LX200Telescope::Goto(double ra, double dec)
328 {
329  const struct timespec timeout = {0, 100000000L};
330 
331  targetRA = ra;
332  targetDEC = dec;
333  char RAStr[64] = {0}, DecStr[64] = {0};
334  int fracbase = 0;
335 
336  switch (getLX200EquatorialFormat())
337  {
339  fracbase = 360000;
340  break;
343  default:
344  fracbase = 3600;
345  break;
346  }
347 
348  fs_sexa(RAStr, targetRA, 2, fracbase);
349  fs_sexa(DecStr, targetDEC, 2, fracbase);
350 
351  // If moving, let's stop it first.
352  if (EqNP.s == IPS_BUSY)
353  {
354  if (!isSimulation() && abortSlew(PortFD) < 0)
355  {
356  AbortSP.s = IPS_ALERT;
357  IDSetSwitch(&AbortSP, "Abort slew failed.");
358  return false;
359  }
360 
361  AbortSP.s = IPS_OK;
362  EqNP.s = IPS_IDLE;
363  IDSetSwitch(&AbortSP, "Slew aborted.");
364  IDSetNumber(&EqNP, nullptr);
365 
367  {
370  EqNP.s = IPS_IDLE;
373  IDSetSwitch(&MovementNSSP, nullptr);
374  IDSetSwitch(&MovementWESP, nullptr);
375  }
376 
377  // sleep for 100 mseconds
378  nanosleep(&timeout, nullptr);
379  }
380 
381  if (!isSimulation())
382  {
384  {
385  EqNP.s = IPS_ALERT;
386  IDSetNumber(&EqNP, "Error setting RA/DEC.");
387  return false;
388  }
389 
390  int err = 0;
391 
392  /* Slew reads the '0', that is not the end of the slew */
393  if ((err = Slew(PortFD)))
394  {
395  LOGF_ERROR("Error Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
396  slewError(err);
397  return false;
398  }
399  }
400 
402  //EqNP.s = IPS_BUSY;
403 
404  LOGF_INFO("Slewing to RA: %s - DEC: %s", RAStr, DecStr);
405 
406  return true;
407 }
408 
409 bool LX200Telescope::Sync(double ra, double dec)
410 {
411  char syncString[256] = {0};
412 
413  if (!isSimulation() && (setObjectRA(PortFD, ra) < 0 || (setObjectDEC(PortFD, dec)) < 0))
414  {
415  EqNP.s = IPS_ALERT;
416  IDSetNumber(&EqNP, "Error setting RA/DEC. Unable to Sync.");
417  return false;
418  }
419 
420  if (!isSimulation() && ::Sync(PortFD, syncString) < 0)
421  {
422  EqNP.s = IPS_ALERT;
423  IDSetNumber(&EqNP, "Synchronization failed.");
424  return false;
425  }
426 
427  currentRA = ra;
428  currentDEC = dec;
429 
430  LOG_INFO("Synchronization successful.");
431 
432  EqNP.s = IPS_OK;
433 
435 
436  return true;
437 }
438 
440 {
441  const struct timespec timeout = {0, 100000000L};
442  if (!isSimulation())
443  {
444  // If scope is moving, let's stop it first.
445  if (EqNP.s == IPS_BUSY)
446  {
447  if (!isSimulation() && abortSlew(PortFD) < 0)
448  {
449  AbortSP.s = IPS_ALERT;
450  IDSetSwitch(&AbortSP, "Abort slew failed.");
451  return false;
452  }
453 
454  AbortSP.s = IPS_OK;
455  EqNP.s = IPS_IDLE;
456  IDSetSwitch(&AbortSP, "Slew aborted.");
457  IDSetNumber(&EqNP, nullptr);
458 
460  {
463  EqNP.s = IPS_IDLE;
466 
467  IDSetSwitch(&MovementNSSP, nullptr);
468  IDSetSwitch(&MovementWESP, nullptr);
469  }
470 
471  // sleep for 100 msec
472  nanosleep(&timeout, nullptr);
473  }
474 
475  if (!isSimulation() && slewToPark(PortFD) < 0)
476  {
477  ParkSP.s = IPS_ALERT;
478  IDSetSwitch(&ParkSP, "Parking Failed.");
479  return false;
480  }
481  }
482 
484  LOG_INFO("Parking telescope in progress...");
485  return true;
486 }
487 
489 {
490  int current_move = (dir == DIRECTION_NORTH) ? LX200_NORTH : LX200_SOUTH;
491 
492  switch (command)
493  {
494  case MOTION_START:
495  if (!isSimulation() && MoveTo(PortFD, current_move) < 0)
496  {
497  LOG_ERROR("Error setting N/S motion direction.");
498  return false;
499  }
500  else
501  LOGF_DEBUG("Moving toward %s.",
502  (current_move == LX200_NORTH) ? "North" : "South");
503  break;
504 
505  case MOTION_STOP:
506  if (!isSimulation() && HaltMovement(PortFD, current_move) < 0)
507  {
508  LOG_ERROR("Error stopping N/S motion.");
509  return false;
510  }
511  else
512  LOGF_DEBUG("Movement toward %s halted.",
513  (current_move == LX200_NORTH) ? "North" : "South");
514  break;
515  }
516 
517  return true;
518 }
519 
521 {
522  int current_move = (dir == DIRECTION_WEST) ? LX200_WEST : LX200_EAST;
523 
524  switch (command)
525  {
526  case MOTION_START:
527  if (!isSimulation() && MoveTo(PortFD, current_move) < 0)
528  {
529  LOG_ERROR("Error setting W/E motion direction.");
530  return false;
531  }
532  else
533  LOGF_DEBUG("Moving toward %s.", (current_move == LX200_WEST) ? "West" : "East");
534  break;
535 
536  case MOTION_STOP:
537  if (!isSimulation() && HaltMovement(PortFD, current_move) < 0)
538  {
539  LOG_ERROR("Error stopping W/E motion.");
540  return false;
541  }
542  else
543  LOGF_DEBUG("Movement toward %s halted.",
544  (current_move == LX200_WEST) ? "West" : "East");
545  break;
546  }
547 
548  return true;
549 }
550 
552 {
553  if (!isSimulation() && abortSlew(PortFD) < 0)
554  {
555  LOG_ERROR("Failed to abort slew.");
556  return false;
557  }
558 
559  if (GuideNSNP.s == IPS_BUSY || GuideWENP.s == IPS_BUSY)
560  {
562  GuideNSN[0].value = GuideNSN[1].value = 0.0;
563  GuideWEN[0].value = GuideWEN[1].value = 0.0;
564 
565  if (GuideNSTID)
566  {
568  GuideNSTID = 0;
569  }
570 
571  if (GuideWETID)
572  {
574  GuideNSTID = 0;
575  }
576 
577  LOG_INFO("Guide aborted.");
578  IDSetNumber(&GuideNSNP, nullptr);
579  IDSetNumber(&GuideWENP, nullptr);
580 
581  return true;
582  }
583 
584  return true;
585 }
586 
587 bool LX200Telescope::setLocalDate(uint8_t days, uint8_t months, uint16_t years)
588 {
589  return (setCalenderDate(PortFD, days, months, years) == 0);
590 }
591 
592 bool LX200Telescope::setLocalTime24(uint8_t hour, uint8_t minute, uint8_t second)
593 {
594  return (setLocalTime(PortFD, hour, minute, second) == 0);
595 }
596 
597 bool LX200Telescope::setUTCOffset(double offset)
598 {
599  return (::setUTCOffset(PortFD, (offset * -1.0)) == 0);
600 }
601 
602 bool LX200Telescope::updateTime(ln_date *utc, double utc_offset)
603 {
604  struct ln_zonedate ltm;
605 
606  if (isSimulation())
607  return true;
608 
609  ln_date_to_zonedate(utc, &ltm, utc_offset * 3600.0);
610 
611  JD = ln_get_julian_day(utc);
612 
613  LOGF_DEBUG("New JD is %.2f", JD);
614 
615  // Meade defines UTC Offset as the offset ADDED to local time to yield UTC, which
616  // is the opposite of the standard definition of UTC offset!
617  if (setUTCOffset(utc_offset) == false)
618  {
619  LOG_ERROR("Error setting UTC Offset.");
620  return false;
621  }
622 
623  // Set Local Time
624  if (setLocalTime24(ltm.hours, ltm.minutes, ltm.seconds) == false)
625  {
626  LOG_ERROR("Error setting local time.");
627  return false;
628  }
629 
630  if (setLocalDate(ltm.days, ltm.months, ltm.years) == false)
631  {
632  LOG_ERROR("Error setting local date.");
633  return false;
634  }
635 
636  LOG_INFO("Time updated, updating planetary data...");
637  return true;
638 }
639 
640 bool LX200Telescope::updateLocation(double latitude, double longitude, double elevation)
641 {
642  INDI_UNUSED(elevation);
643 
644  // JM 2021-04-10: MUST convert from INDI longitude to standard longitude.
645  // DO NOT REMOVE
646  if (longitude > 180)
647  longitude = longitude - 360;
648 
649  if (!isSimulation())
650  {
651  if (setSiteLongitude(PortFD, longitude) < 0)
652  {
653  LOG_ERROR("Error setting site longitude coordinates");
654  return false;
655  }
656 
657  if (setSiteLatitude(PortFD, latitude) < 0)
658  {
659  LOG_ERROR("Error setting site latitude coordinates");
660  return false;
661  }
662  }
663 
664  char l[MAXINDINAME] = {0}, L[MAXINDINAME] = {0};
665  fs_sexa(l, latitude, 2, 36000);
666  fs_sexa(L, longitude, 2, 36000);
667 
668  // Choose WGS 84, also known as EPSG:4326 for latitude/longitude ordering
669  LOGF_INFO("Site location in the mount updated to Latitude %.12s (%g) Longitude %.12s (%g) (Longitude sign in carthography format)",
670  l, latitude, L, longitude);
671 
672  return true;
673 }
674 
675 bool LX200Telescope::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
676 {
677  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
678  {
679  if (!strcmp(name, SiteNameTP.name))
680  {
681  if (!isSimulation() && setSiteName(PortFD, texts[0], currentSiteNum) < 0)
682  {
684  IDSetText(&SiteNameTP, "Setting site name");
685  return false;
686  }
687 
688  SiteNameTP.s = IPS_OK;
689  IText *tp = IUFindText(&SiteNameTP, names[0]);
690  IUSaveText(tp, texts[0]);
691  IDSetText(&SiteNameTP, "Site name updated");
692  return true;
693  }
694  }
695 
696  return INDI::Telescope::ISNewText(dev, name, texts, names, n);
697 }
698 
699 bool LX200Telescope::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
700 {
701  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
702  {
703  if (strstr(name, "FOCUS_"))
704  {
705  return FI::processNumber(dev, name, values, names, n);
706  }
707 
708  // Update Frequency
709  if (!strcmp(name, TrackFreqNP.name))
710  {
711  LOGF_DEBUG("Trying to set track freq of: %04.1f", values[0]);
713  {
714  if (!isSimulation() && setPreciseTrackFreq(PortFD, values[0]) < 0)
715  {
717  IDSetNumber(&TrackFreqNP, "Error setting tracking frequency");
718  return false;
719  }
720  TrackFreqNP.s = IPS_OK;
721  TrackFreqNP.np[0].value = values[0];
722  IDSetNumber(&TrackFreqNP, "Tracking frequency set to %8.5f", values[0]);
723  }
724  else
725  {
726  //Normal Tracking Frequency
727  if (!isSimulation() && setTrackFreq(PortFD, values[0]) < 0)
728 
729  LOGF_DEBUG("Trying to set track freq of: %f\n", values[0]);
730  if (!isSimulation() && setTrackFreq(PortFD, values[0]) < 0)
731  {
732  LOGF_DEBUG("Trying to set track freq of: %f\n", values[0]);
733  if (!isSimulation() && setTrackFreq(PortFD, values[0]) < 0)
734  {
736  IDSetNumber(&TrackFreqNP, "Error setting tracking frequency");
737  return false;
738  }
739  TrackFreqNP.s = IPS_OK;
740  IDSetNumber(&TrackFreqNP, "Error setting tracking frequency");
741  return false;
742  }
743 
744  TrackFreqNP.s = IPS_OK;
745  TrackFreqNP.np[0].value = values[0];
746  IDSetNumber(&TrackFreqNP, "Tracking frequency set to %04.1f", values[0]);
747  }
748 
750  {
752  TrackModeS[0].s = ISS_OFF;
753  TrackModeS[1].s = ISS_OFF;
754  TrackModeS[2].s = ISS_OFF;
755  TrackModeS[3].s = ISS_ON;
756  TrackModeSP.s = IPS_OK;
758  IDSetSwitch(&TrackModeSP, nullptr);
759  }
760 
761  return true;
762  }
763 
764  // if (!strcmp(name, FocusTimerNP.name))
765  // {
766  // // Don't update if busy
767  // if (FocusTimerNP.s == IPS_BUSY)
768  // return true;
769 
770  // IUUpdateNumber(&FocusTimerNP, values, names, n);
771 
772  // FocusTimerNP.s = IPS_OK;
773 
774  // IDSetNumber(&FocusTimerNP, nullptr);
775 
776  // LOGF_DEBUG("Setting focus timer to %.2f", FocusTimerN[0].value);
777 
778  // return true;
779  // }
780 
781  processGuiderProperties(name, values, names, n);
782  }
783 
784  // if we didn't process it, continue up the chain, let somebody else
785  // give it a shot
786  return INDI::Telescope::ISNewNumber(dev, name, values, names, n);
787 }
788 
789 bool LX200Telescope::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
790 {
791  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
792  {
793  // Focuser
794  if (strstr(name, "FOCUS"))
795  {
796  return FI::processSwitch(dev, name, states, names, n);
797  }
798 
799  // Alignment
800  if (!strcmp(name, AlignmentSP.name))
801  {
802  if (IUUpdateSwitch(&AlignmentSP, states, names, n) < 0)
803  return false;
804 
805  int index = IUFindOnSwitchIndex(&AlignmentSP);
806 
807  if (!isSimulation() && setAlignmentMode(PortFD, index) < 0)
808  {
810  IDSetSwitch(&AlignmentSP, "Error setting alignment mode.");
811  return false;
812  }
813 
814  AlignmentSP.s = IPS_OK;
815  IDSetSwitch(&AlignmentSP, nullptr);
816  return true;
817  }
818 
819  // Sites
820  if (!strcmp(name, SiteSP.name))
821  {
822  if (IUUpdateSwitch(&SiteSP, states, names, n) < 0)
823  return false;
824 
826 
828  {
829  SiteSP.s = IPS_ALERT;
830  IDSetSwitch(&SiteSP, "Error selecting sites.");
831  return false;
832  }
833  char siteName[64] = {0};
834  if (isSimulation())
835  {
836  IUSaveText(&SiteNameTP.tp[0], "Sample Site");
837  }
838  else
839  {
840  getSiteName(PortFD, siteName, currentSiteNum);
841  IUSaveText(&SiteNameT[0], siteName);
842  }
845 
846  SiteNameTP.s = IPS_OK;
847  SiteSP.s = IPS_OK;
848 
849  IDSetText(&SiteNameTP, nullptr);
850  IDSetSwitch(&SiteSP, nullptr);
851 
852  return false;
853  }
854 
855  // // Focus Motion
856  // if (!strcmp(name, FocusMotionSP.name))
857  // {
858  // // If mode is "halt"
859  // if (FocusModeS[0].s == ISS_ON)
860  // {
861  // FocusMotionSP.s = IPS_IDLE;
862  // IDSetSwitch(&FocusMotionSP, "Focus mode is halt. Select slow or fast mode");
863  // return true;
864  // }
865 
866  // int last_motion = IUFindOnSwitchIndex(&FocusMotionSP);
867 
868  // if (IUUpdateSwitch(&FocusMotionSP, states, names, n) < 0)
869  // return false;
870 
871  // index = IUFindOnSwitchIndex(&FocusMotionSP);
872 
873  // // If same direction and we're busy, stop
874  // if (last_motion == index && FocusMotionSP.s == IPS_BUSY)
875  // {
876  // IUResetSwitch(&FocusMotionSP);
877  // FocusMotionSP.s = IPS_IDLE;
878  // setFocuserSpeedMode(PortFD, 0);
879  // IDSetSwitch(&FocusMotionSP, nullptr);
880  // return true;
881  // }
882 
883  // if (!isSimulation() && setFocuserMotion(PortFD, index) < 0)
884  // {
885  // FocusMotionSP.s = IPS_ALERT;
886  // IDSetSwitch(&FocusMotionSP, "Error setting focuser speed.");
887  // return false;
888  // }
889 
890  // // with a timer
891  // if (FocusTimerN[0].value > 0)
892  // {
893  // FocusTimerNP.s = IPS_BUSY;
894  // FocusMotionSP.s = IPS_BUSY;
895  // IEAddTimer(50, LX200Telescope::updateFocusHelper, this);
896  // }
897 
898  // FocusMotionSP.s = IPS_OK;
899  // IDSetSwitch(&FocusMotionSP, nullptr);
900  // return true;
901  // }
902 
903  // // Focus speed
904  // if (!strcmp(name, FocusModeSP.name))
905  // {
906  // IUResetSwitch(&FocusModeSP);
907  // IUUpdateSwitch(&FocusModeSP, states, names, n);
908 
909  // index = IUFindOnSwitchIndex(&FocusModeSP);
910 
911  // /* disable timer and motion */
912  // if (index == 0)
913  // {
914  // IUResetSwitch(&FocusMotionSP);
915  // FocusMotionSP.s = IPS_IDLE;
916  // FocusTimerNP.s = IPS_IDLE;
917  // IDSetSwitch(&FocusMotionSP, nullptr);
918  // IDSetNumber(&FocusTimerNP, nullptr);
919  // }
920 
921  // if (!isSimulation())
922  // setFocuserSpeedMode(PortFD, index);
923  // FocusModeSP.s = IPS_OK;
924  // IDSetSwitch(&FocusModeSP, nullptr);
925  // return true;
926  // }
927 
928  // Pulse-Guide command support
929  if (!strcmp(name, UsePulseCmdSP.name))
930  {
932  IUUpdateSwitch(&UsePulseCmdSP, states, names, n);
933 
935  IDSetSwitch(&UsePulseCmdSP, nullptr);
936  usePulseCommand = (UsePulseCmdS[1].s == ISS_ON);
937  LOGF_INFO("Pulse guiding is %s.", usePulseCommand ? "enabled" : "disabled");
938  return true;
939  }
940  }
941 
942  // Nobody has claimed this, so pass it to the parent
943  return INDI::Telescope::ISNewSwitch(dev, name, states, names, n);
944 }
945 
947 {
948  if (isSimulation())
949  return true;
950 
951  bool rc = (selectTrackingMode(PortFD, mode) == 0);
952 
953  // Only update tracking frequency if it is defined and not deleted by child classes
954  // Note, that LX200_HAS_PRECISE_TRACKING_FREQ can use the same get function
956  {
957  getTrackFreq(PortFD, &TrackFreqN[0].value);
958  IDSetNumber(&TrackFreqNP, nullptr);
959  }
960  return rc;
961 }
962 
964 {
965  // Convert index to Meade format
966  index = 3 - index;
967 
968  if (!isSimulation() && setSlewMode(PortFD, index) < 0)
969  {
970  LOG_ERROR("Error setting slew mode.");
971  return false;
972  }
973 
974  return true;
975 }
976 
978 {
979  if (IUFindOnSwitchIndex(&SlewRateSP) == index)
980  return true;
981 
982  if (!isSimulation() && setSlewMode(PortFD, 3 - index) < 0)
983  {
985  IDSetSwitch(&SlewRateSP, "Error setting slew mode.");
986  return false;
987  }
988 
990  SlewRateS[index].s = ISS_ON;
991  SlewRateSP.s = IPS_OK;
992  IDSetSwitch(&SlewRateSP, nullptr);
993  return true;
994 }
995 
997 {
998  static_cast<LX200Telescope *>(p)->updateFocusTimer();
999 }
1000 
1002 {
1003  // switch (FocusTimerNP.s)
1004  // {
1005  // case IPS_IDLE:
1006  // break;
1007 
1008  // case IPS_BUSY:
1009  // //if (isDebug())
1010  // //IDLog("Focus Timer Value is %g\n", FocusTimerN[0].value);
1011 
1012  // FocusTimerN[0].value -= 50;
1013 
1014  // if (FocusTimerN[0].value <= 0)
1015  // {
1016  // //if (isDebug())
1017  // //IDLog("Focus Timer Expired\n");
1018 
1019  // if (!isSimulation() && setFocuserSpeedMode(PortFD, 0) < 0)
1020  // {
1021  // FocusModeSP.s = IPS_ALERT;
1022  // IDSetSwitch(&FocusModeSP, "Error setting focuser mode.");
1023 
1024  // //if (isDebug())
1025  // //IDLog("Error setting focuser mode\n");
1026 
1027  // return;
1028  // }
1029 
1030  // FocusMotionSP.s = IPS_IDLE;
1031  // FocusTimerNP.s = IPS_OK;
1032  // FocusModeSP.s = IPS_OK;
1033 
1034  // IUResetSwitch(&FocusMotionSP);
1035  // IUResetSwitch(&FocusModeSP);
1036  // FocusModeS[0].s = ISS_ON;
1037 
1038  // IDSetSwitch(&FocusModeSP, nullptr);
1039  // IDSetSwitch(&FocusMotionSP, nullptr);
1040  // }
1041 
1042  // IDSetNumber(&FocusTimerNP, nullptr);
1043 
1044  // if (FocusTimerN[0].value > 0)
1045  // IEAddTimer(50, LX200Telescope::updateFocusHelper, this);
1046  // break;
1047 
1048  // case IPS_OK:
1049  // break;
1050 
1051  // case IPS_ALERT:
1052  // break;
1053  // }
1054 
1055  AbortFocuser();
1056  FocusTimerNP.s = IPS_OK;
1057  FocusTimerN[0].value = 0;
1058  IDSetNumber(&FocusTimerNP, nullptr);
1059 }
1060 
1062 {
1063  static struct timeval ltv;
1064  struct timeval tv;
1065  double dt = 0, da = 0, dx = 0;
1066  int nlocked = 0;
1067 
1068  /* update elapsed time since last poll, don't presume exactly POLLMS */
1069  gettimeofday(&tv, nullptr);
1070 
1071  if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
1072  ltv = tv;
1073 
1074  dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
1075  ltv = tv;
1076  da = LX200_GENERIC_SLEWRATE * dt;
1077 
1078  /* Process per current state. We check the state of EQUATORIAL_COORDS and act acoordingly */
1079  switch (TrackState)
1080  {
1081 
1082  case SCOPE_IDLE:
1083  currentRA += (TRACKRATE_SIDEREAL / 3600.0 * dt / 15.);
1084  break;
1085 
1086  case SCOPE_TRACKING:
1087  switch (IUFindOnSwitchIndex(&TrackModeSP))
1088  {
1089  case TRACK_SIDEREAL:
1090  da = 0;
1091  dx = 0;
1092  break;
1093 
1094  case TRACK_LUNAR:
1095  da = ((TRACKRATE_LUNAR - TRACKRATE_SIDEREAL) / 3600.0 * dt / 15.);
1096  dx = 0;
1097  break;
1098 
1099  case TRACK_SOLAR:
1100  da = ((TRACKRATE_SOLAR - TRACKRATE_SIDEREAL) / 3600.0 * dt / 15.);
1101  dx = 0;
1102  break;
1103 
1104  case TRACK_CUSTOM:
1105  da = ((TrackRateN[AXIS_RA].value - TRACKRATE_SIDEREAL) / 3600.0 * dt / 15.);
1106  dx = (TrackRateN[AXIS_DE].value / 3600.0 * dt);
1107  break;
1108 
1109  }
1110 
1111  currentRA += da;
1112  currentDEC += dx;
1113  break;
1114 
1115  case SCOPE_SLEWING:
1116  case SCOPE_PARKING:
1117  /* slewing - nail it when both within one pulse @ LX200_GENERIC_SLEWRATE */
1118  nlocked = 0;
1119 
1120  dx = targetRA - currentRA;
1121 
1122  if (fabs(dx) <= da)
1123  {
1124  currentRA = targetRA;
1125  nlocked++;
1126  }
1127  else if (dx > 0)
1128  currentRA += da / 15.;
1129  else
1130  currentRA -= da / 15.;
1131 
1132  dx = targetDEC - currentDEC;
1133  if (fabs(dx) <= da)
1134  {
1136  nlocked++;
1137  }
1138  else if (dx > 0)
1139  currentDEC += da;
1140  else
1141  currentDEC -= da;
1142 
1143  if (nlocked == 2)
1144  {
1145  if (TrackState == SCOPE_SLEWING)
1147  else
1148  SetParked(true);
1149  }
1150 
1151  break;
1152 
1153  default:
1154  break;
1155  }
1156 
1158 }
1159 
1161 {
1162  if (!isSimulation())
1163  {
1165 
1167  getAlignment();
1168 
1169  // Only check time format if it is not already initialized by the class
1171  {
1172  if (getTimeFormat(PortFD, &timeFormat) < 0)
1173  LOG_ERROR("Failed to retrieve time format from device.");
1174  else
1175  {
1176  timeFormat = (timeFormat == 24) ? LX200_24 : LX200_AM;
1177  // We always do 24 hours
1178  if (timeFormat != LX200_24)
1179  {
1180  // Toggle format and suppress gcc warning
1181  int rc = toggleTimeFormat(PortFD);
1182  INDI_UNUSED(rc);
1183  }
1184  }
1185  }
1186 
1188  {
1189  char siteName[64] = {0};
1190  if (getSiteName(PortFD, siteName, currentSiteNum) < 0)
1191  {
1192  LOG_ERROR("Failed to get site name from device");
1193  }
1194  else
1195  {
1196  IUSaveText(&SiteNameT[0], siteName);
1197  IDSetText(&SiteNameTP, nullptr);
1198  }
1199  }
1200 
1201 
1203  {
1204  if (getTrackFreq(PortFD, &TrackFreqN[0].value) < 0)
1205  LOG_ERROR("Failed to get tracking frequency from device.");
1206  else
1207  IDSetNumber(&TrackFreqNP, nullptr);
1208  }
1209 
1210  }
1211 
1215  sendScopeTime();
1216 }
1217 
1218 void LX200Telescope::slewError(int slewCode)
1219 {
1220  if (slewCode == 1)
1221  LOG_ERROR("Object below horizon.");
1222  else if (slewCode == 2)
1223  LOG_ERROR("Object below the minimum elevation limit.");
1224  else
1225  LOGF_ERROR("Slew failed (%d).", slewCode);
1226 
1227  EqNP.s = IPS_ALERT;
1228  IDSetNumber(&EqNP, nullptr);
1229 }
1230 
1232 {
1233  signed char align = ACK(PortFD);
1234  if (align < 0)
1235  {
1236  IDSetSwitch(&AlignmentSP, "Failed to get telescope alignment.");
1237  return;
1238  }
1239 
1240  AlignmentS[0].s = ISS_OFF;
1241  AlignmentS[1].s = ISS_OFF;
1242  AlignmentS[2].s = ISS_OFF;
1243 
1244  switch (align)
1245  {
1246  case 'P':
1247  AlignmentS[0].s = ISS_ON;
1248  break;
1249  case 'A':
1250  AlignmentS[1].s = ISS_ON;
1251  break;
1252  case 'L':
1253  AlignmentS[2].s = ISS_ON;
1254  break;
1255  }
1256 
1257  AlignmentSP.s = IPS_OK;
1258  IDSetSwitch(&AlignmentSP, nullptr);
1259 }
1260 
1261 bool LX200Telescope::getLocalTime(char *timeString)
1262 {
1263  if (isSimulation())
1264  {
1265  time_t now = time (nullptr);
1266  strftime(timeString, MAXINDINAME, "%T", localtime(&now));
1267  }
1268  else
1269  {
1270  double ctime = 0;
1271  int h, m, s;
1272  getLocalTime24(PortFD, &ctime);
1273  getSexComponents(ctime, &h, &m, &s);
1274  snprintf(timeString, MAXINDINAME, "%02d:%02d:%02d", h, m, s);
1275  }
1276 
1277  return true;
1278 }
1279 
1280 bool LX200Telescope::getLocalDate(char *dateString)
1281 {
1282  if (isSimulation())
1283  {
1284  time_t now = time (nullptr);
1285  strftime(dateString, MAXINDINAME, "%F", localtime(&now));
1286  }
1287  else
1288  {
1289  getCalendarDate(PortFD, dateString);
1290  }
1291 
1292  return true;
1293 }
1294 
1295 bool LX200Telescope::getUTFOffset(double *offset)
1296 {
1297  if (isSimulation())
1298  {
1299  *offset = 3;
1300  return true;
1301  }
1302 
1303  int lx200_utc_offset = 0;
1304  getUTCOffset(PortFD, &lx200_utc_offset);
1305  // LX200 TimeT Offset is defined at the number of hours added to LOCAL TIME to get TimeT. This is contrary to the normal definition.
1306  *offset = lx200_utc_offset * -1;
1307  return true;
1308 }
1309 
1311 {
1312  char cdate[MAXINDINAME] = {0};
1313  char ctime[MAXINDINAME] = {0};
1314  struct tm ltm;
1315  struct tm utm;
1316  time_t time_epoch;
1317 
1318  double offset = 0;
1319  if (getUTFOffset(&offset))
1320  {
1321  char utcStr[8] = {0};
1322  snprintf(utcStr, 8, "%.2f", offset);
1323  IUSaveText(&TimeT[1], utcStr);
1324  }
1325  else
1326  {
1327  LOG_WARN("Could not obtain UTC offset from mount!");
1328  return false;
1329  }
1330 
1331  if (getLocalTime(ctime) == false)
1332  {
1333  LOG_WARN("Could not obtain local time from mount!");
1334  return false;
1335  }
1336 
1337  if (getLocalDate(cdate) == false)
1338  {
1339  LOG_WARN("Could not obtain local date from mount!");
1340  return false;
1341  }
1342 
1343  // To ISO 8601 format in LOCAL TIME!
1344  char datetime[MAXINDINAME] = {0};
1345  snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);
1346 
1347  // Now that date+time are combined, let's get tm representation of it.
1348  if (strptime(datetime, "%FT%T", &ltm) == nullptr)
1349  {
1350  LOGF_WARN("Could not process mount date and time: %s", datetime);
1351  return false;
1352  }
1353 
1354  // Get local time epoch in UNIX seconds
1355  time_epoch = mktime(&ltm);
1356 
1357  // LOCAL to UTC by subtracting offset.
1358  time_epoch -= static_cast<int>(offset * 3600.0);
1359 
1360  // Get UTC (we're using localtime_r, but since we shifted time_epoch above by UTCOffset, we should be getting the real UTC time)
1361  localtime_r(&time_epoch, &utm);
1362 
1363  // Format it into the final UTC ISO 8601
1364  strftime(cdate, MAXINDINAME, "%Y-%m-%dT%H:%M:%S", &utm);
1365  IUSaveText(&TimeT[0], cdate);
1366 
1367  LOGF_DEBUG("Mount controller UTC Time: %s", TimeT[0].text);
1368  LOGF_DEBUG("Mount controller UTC Offset: %s", TimeT[1].text);
1369 
1370  // Let's send everything to the client
1371  TimeTP.s = IPS_OK;
1372  IDSetText(&TimeTP, nullptr);
1373 
1374  return true;
1375 }
1376 
1378 {
1379  int lat_dd = 0, lat_mm = 0, long_dd = 0, long_mm = 0;
1380  double lat_ssf = 0.0, long_ssf = 0.0;
1381  char lat_sexagesimal[MAXINDIFORMAT];
1382  char lng_sexagesimal[MAXINDIFORMAT];
1383 
1384  if (isSimulation())
1385  {
1386  LocationNP.np[LOCATION_LATITUDE].value = 29.5;
1387  LocationNP.np[LOCATION_LONGITUDE].value = 48.0;
1388  LocationNP.np[LOCATION_ELEVATION].value = 10;
1389  LocationNP.s = IPS_OK;
1390  IDSetNumber(&LocationNP, nullptr);
1391  return true;
1392  }
1393 
1394  if (getSiteLatitude(PortFD, &lat_dd, &lat_mm, &lat_ssf) < 0)
1395  {
1396  LOG_WARN("Failed to get site latitude from device.");
1397  return false;
1398  }
1399  else
1400  {
1401  snprintf(lat_sexagesimal, MAXINDIFORMAT, "%02d:%02d:%02.1lf", lat_dd, lat_mm, lat_ssf);
1402  f_scansexa(lat_sexagesimal, &(LocationNP.np[LOCATION_LATITUDE].value));
1403  }
1404 
1405  if (getSiteLongitude(PortFD, &long_dd, &long_mm, &long_ssf) < 0)
1406  {
1407  LOG_WARN("Failed to get site longitude from device.");
1408  return false;
1409  }
1410  else
1411  {
1412  snprintf(lng_sexagesimal, MAXINDIFORMAT, "%02d:%02d:%02.1lf", long_dd, long_mm, long_ssf);
1413  f_scansexa(lng_sexagesimal, &(LocationNP.np[LOCATION_LONGITUDE].value));
1414  }
1415 
1416  LOGF_INFO("Mount has Latitude %s (%g) Longitude %s (%g) (Longitude sign in carthography format)",
1417  lat_sexagesimal,
1419  lng_sexagesimal,
1420  LocationN[LOCATION_LONGITUDE].value);
1421 
1422  IDSetNumber(&LocationNP, nullptr);
1423 
1424  saveConfig(true, "GEOGRAPHIC_COORD");
1425 
1426  return true;
1427 }
1428 
1430 {
1432  {
1433  LOG_ERROR("Cannot guide while slewing or parking in progress. Stop first.");
1434  return IPS_ALERT;
1435  }
1436 
1437  // If we're using pulse command, then MovementXXX should NOT be active at all.
1439  {
1440  LOG_ERROR("Cannot pulse guide while manually in motion. Stop first.");
1441  return IPS_ALERT;
1442  }
1443 
1444  if (GuideNSTID)
1445  {
1447  GuideNSTID = 0;
1448  }
1449 
1450  if (usePulseCommand)
1451  {
1453  }
1454  else
1455  {
1457 
1458  ISState states[] = { ISS_ON, ISS_OFF };
1459  const char *names[] = { MovementNSS[DIRECTION_NORTH].name, MovementNSS[DIRECTION_SOUTH].name};
1460  ISNewSwitch(MovementNSSP.device, MovementNSSP.name, states, const_cast<char **>(names), 2);
1461  }
1462 
1464  GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperNS, this);
1465  return IPS_BUSY;
1466 }
1467 
1469 {
1471  {
1472  LOG_ERROR("Cannot guide while slewing or parking in progress. Stop first.");
1473  return IPS_ALERT;
1474  }
1475 
1476  // If we're using pulse command, then MovementXXX should NOT be active at all.
1478  {
1479  LOG_ERROR("Cannot pulse guide while manually in motion. Stop first.");
1480  return IPS_ALERT;
1481  }
1482 
1483  if (GuideNSTID)
1484  {
1486  GuideNSTID = 0;
1487  }
1488 
1489  if (usePulseCommand)
1490  {
1492  }
1493  else
1494  {
1496 
1497  ISState states[] = { ISS_OFF, ISS_ON };
1498  const char *names[] = { MovementNSS[DIRECTION_NORTH].name, MovementNSS[DIRECTION_SOUTH].name};
1499  ISNewSwitch(MovementNSSP.device, MovementNSSP.name, states, const_cast<char **>(names), 2);
1500  }
1501 
1503  GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperNS, this);
1504  return IPS_BUSY;
1505 }
1506 
1508 {
1510  {
1511  LOG_ERROR("Cannot guide while slewing or parking in progress. Stop first.");
1512  return IPS_ALERT;
1513  }
1514 
1515  // If we're using pulse command, then MovementXXX should NOT be active at all.
1517  {
1518  LOG_ERROR("Cannot pulse guide while manually in motion. Stop first.");
1519  return IPS_ALERT;
1520  }
1521 
1522  if (GuideWETID)
1523  {
1525  GuideWETID = 0;
1526  }
1527 
1528  if (usePulseCommand)
1529  {
1530  SendPulseCmd(LX200_EAST, ms);
1531  }
1532  else
1533  {
1535 
1536  ISState states[] = { ISS_OFF, ISS_ON };
1537  const char *names[] = { MovementWES[DIRECTION_WEST].name, MovementWES[DIRECTION_EAST].name};
1538  ISNewSwitch(MovementWESP.device, MovementWESP.name, states, const_cast<char **>(names), 2);
1539  }
1540 
1542  GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperWE, this);
1543  return IPS_BUSY;
1544 }
1545 
1547 {
1549  {
1550  LOG_ERROR("Cannot guide while slewing or parking in progress. Stop first.");
1551  return IPS_ALERT;
1552  }
1553 
1554  // If we're using pulse command, then MovementXXX should NOT be active at all.
1556  {
1557  LOG_ERROR("Cannot pulse guide while manually in motion. Stop first.");
1558  return IPS_ALERT;
1559  }
1560 
1561  if (GuideWETID)
1562  {
1564  GuideWETID = 0;
1565  }
1566 
1567  if (usePulseCommand)
1568  {
1569  SendPulseCmd(LX200_WEST, ms);
1570  }
1571  else
1572  {
1574 
1575  ISState states[] = { ISS_ON, ISS_OFF };
1576  const char *names[] = { MovementWES[DIRECTION_WEST].name, MovementWES[DIRECTION_EAST].name};
1577  ISNewSwitch(MovementWESP.device, MovementWESP.name, states, const_cast<char **>(names), 2);
1578  }
1579 
1581  GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperWE, this);
1582  return IPS_BUSY;
1583 }
1584 
1585 int LX200Telescope::SendPulseCmd(int8_t direction, uint32_t duration_msec)
1586 {
1587  return ::SendPulseCmd(PortFD, direction, duration_msec);
1588 }
1589 
1591 {
1592  static_cast<LX200Telescope *>(p)->guideTimeoutNS();
1593 }
1594 
1596 {
1597  static_cast<LX200Telescope *>(p)->guideTimeoutWE();
1598 }
1599 
1601 {
1602  if (usePulseCommand == false)
1603  {
1604  ISState states[] = { ISS_OFF, ISS_OFF };
1605  const char *names[] = { MovementWES[DIRECTION_WEST].name, MovementWES[DIRECTION_EAST].name};
1606  ISNewSwitch(MovementWESP.device, MovementWESP.name, states, const_cast<char **>(names), 2);
1607  }
1608 
1609  GuideWENP.np[DIRECTION_WEST].value = 0;
1610  GuideWENP.np[DIRECTION_EAST].value = 0;
1611  GuideWENP.s = IPS_IDLE;
1612  GuideWETID = 0;
1613  IDSetNumber(&GuideWENP, nullptr);
1614 }
1615 
1617 {
1618  if (usePulseCommand == false)
1619  {
1620  ISState states[] = { ISS_OFF, ISS_OFF };
1621  const char *names[] = { MovementNSS[DIRECTION_NORTH].name, MovementNSS[DIRECTION_SOUTH].name};
1622  ISNewSwitch(MovementNSSP.device, MovementNSSP.name, states, const_cast<char **>(names), 2);
1623  }
1624 
1625  GuideNSNP.np[0].value = 0;
1626  GuideNSNP.np[1].value = 0;
1627  GuideNSNP.s = IPS_IDLE;
1628  GuideNSTID = 0;
1629  IDSetNumber(&GuideNSNP, nullptr);
1630 
1631 }
1632 
1634 {
1636 
1639 
1641  FI::saveConfigItems(fp);
1642 
1643  return true;
1644 }
1645 
1647 {
1648  INDI_UNUSED(enabled);
1649  return true;
1650 }
1651 
1653 {
1654  return SetFocuserSpeed(0);
1655 }
1656 
1657 IPState LX200Telescope::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
1658 {
1659  FocusDirection finalDirection = dir;
1660  // Reverse final direction if necessary
1661  if (FocusReverseS[INDI_ENABLED].s == ISS_ON)
1662  finalDirection = (dir == FOCUS_INWARD) ? FOCUS_OUTWARD : FOCUS_INWARD;
1663 
1664  SetFocuserSpeed(speed);
1665 
1666  setFocuserMotion(PortFD, finalDirection);
1667 
1669 
1670  return IPS_BUSY;
1671 }
1672 
1674 {
1675  return (setFocuserSpeedMode(PortFD, speed) == 0);
1676 }
1677 
INDI::Telescope::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: inditelescope.cpp:816
getUTCOffset
#define getUTCOffset(fd, x)
Definition: lx200driver.h:137
DIRECTION_NORTH
@ DIRECTION_NORTH
Definition: indibasetypes.h:45
DIRECTION_SOUTH
@ DIRECTION_SOUTH
Definition: indibasetypes.h:46
setSiteLatitude
int setSiteLatitude(int fd, double Lat)
Definition: lx200driver.cpp:1145
INDI::Telescope::SCOPE_IDLE
@ SCOPE_IDLE
Definition: inditelescope.h:75
LX200Telescope::getLocalTime
virtual bool getLocalTime(char *timeString)
Definition: lx200telescope.cpp:1261
LX200Telescope::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: lx200telescope.cpp:1633
setLX200Debug
void setLX200Debug(const char *deviceName, unsigned int debug_level)
Definition: lx200driver.cpp:58
LX200Telescope::mountSim
void mountSim()
Definition: lx200telescope.cpp:1061
INDI::Telescope::SLEW_GUIDE
@ SLEW_GUIDE
Definition: inditelescope.h:88
LX200Telescope::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: lx200telescope.cpp:675
INDI::Telescope::SlewRateS
ISwitch * SlewRateS
Definition: inditelescope.h:750
setSlewMode
int setSlewMode(int fd, int slewMode)
Definition: lx200driver.cpp:1237
INDI::Telescope::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: inditelescope.cpp:658
lx200telescope.h
SendPulseCmd
int SendPulseCmd(int fd, int direction, uint32_t duration_msec)
LX200Telescope::updateSlewRate
bool updateSlewRate(int index)
Definition: lx200telescope.cpp:977
LX200Telescope::getBasicData
virtual void getBasicData()
Definition: lx200telescope.cpp:1160
INDI::DefaultDevice::addAuxControls
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Definition: defaultdevice.cpp:665
LX200Telescope::LX200_HAS_SITES
@ LX200_HAS_SITES
Definition: lx200telescope.h:47
LX200Telescope::setLocalDate
virtual bool setLocalDate(uint8_t days, uint8_t months, uint16_t years)
Definition: lx200telescope.cpp:587
IPState
IPState
Property state.
Definition: indiapi.h:158
LX200Telescope::DBG_SCOPE
uint8_t DBG_SCOPE
Definition: lx200telescope.h:174
_ISwitchVectorProperty::device
char device[MAXINDIDEVICE]
Definition: indiapi.h:368
LX200Telescope::Sync
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
Definition: lx200telescope.cpp:409
INDI::Telescope::initProperties
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition: inditelescope.cpp:82
INDI::Telescope::LocationN
INumber LocationN[3]
Definition: inditelescope.h:719
INDI::Telescope::SCOPE_SLEWING
@ SCOPE_SLEWING
Definition: inditelescope.h:76
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
INDI::Telescope::SCOPE_PARKING
@ SCOPE_PARKING
Definition: inditelescope.h:78
getSiteLatitude
int getSiteLatitude(int fd, int *dd, int *mm, double *ssf)
Definition: lx200driver.cpp:539
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
LX200Telescope::checkConnection
virtual bool checkConnection()
Definition: lx200telescope.cpp:261
getLocalTime24
#define getLocalTime24(fd, x)
Definition: lx200driver.h:122
LX200Telescope::usePulseCommand
bool usePulseCommand
Definition: lx200telescope.h:192
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
MOTION_TAB
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
Definition: defaultdevice.cpp:36
INDI::BaseDevice::GUIDER_INTERFACE
@ GUIDER_INTERFACE
Definition: basedevice.h:74
LX200_EQ_LONGER_FORMAT
@ LX200_EQ_LONGER_FORMAT
Definition: lx200driver.h:52
INDI_DIR_NS
INDI_DIR_NS
Definition: indibasetypes.h:44
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
LX200Telescope::Abort
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
Definition: lx200telescope.cpp:551
getSexComponents
void getSexComponents(double value, int *d, int *m, int *s)
Definition: indicom.c:250
LX200Telescope::guide_direction_we
int8_t guide_direction_we
Definition: lx200telescope.h:167
LX200Telescope::guideTimeoutHelperWE
static void guideTimeoutHelperWE(void *p)
Definition: lx200telescope.cpp:1595
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INDI::Telescope::MovementNSSP
ISwitchVectorProperty MovementNSSP
Definition: inditelescope.h:742
f_scansexa
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double.
Definition: indicom.c:201
LX200Telescope::setUTCOffset
virtual bool setUTCOffset(double offset)
Definition: lx200telescope.cpp:597
INDI::GuiderInterface::GuideWENP
INumberVectorProperty GuideWENP
Definition: indiguiderinterface.h:113
MAXINDINAME
#define MAXINDINAME
Definition: indiapi.h:190
INDI::Telescope::NewRaDec
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
Definition: inditelescope.cpp:693
LX200Telescope::LX200_HAS_PRECISE_TRACKING_FREQ
@ LX200_HAS_PRECISE_TRACKING_FREQ
Definition: lx200telescope.h:49
INDI::DefaultDevice::isSimulation
bool isSimulation() const
Definition: defaultdevice.cpp:734
IUFillNumber
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: indidriver.c:348
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
DIRECTION_EAST
@ DIRECTION_EAST
Definition: indibasetypes.h:52
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
LX200Telescope::sendTimeOnStartup
bool sendTimeOnStartup
Definition: lx200telescope.h:173
INDI_DIR_WE
INDI_DIR_WE
Definition: indibasetypes.h:50
INDI::FocuserInterface::FocusTimerN
INumber FocusTimerN[1]
Definition: indifocuserinterface.h:279
LX200Telescope::GuideWest
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
Definition: lx200telescope.cpp:1546
INDI::Telescope::TrackModeS
ISwitch * TrackModeS
Definition: inditelescope.h:843
LX200Telescope::SetSlewRate
virtual bool SetSlewRate(int index) override
SetSlewRate Set desired slew rate index.
Definition: lx200telescope.cpp:963
selectSite
int selectSite(int fd, int siteNum)
Definition: lx200driver.cpp:1592
IUFillTextVector
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: indidriver.c:477
INDI::FocuserInterface
Provides interface to implement focuser functionality.
Definition: indifocuserinterface.h:63
LX200_NORTH
@ LX200_NORTH
Definition: lx200driver.h:41
INDI::Telescope::LocationNP
INumberVectorProperty LocationNP
Definition: inditelescope.h:718
setSiteName
int setSiteName(int fd, char *siteName, int siteNum)
Definition: lx200driver.cpp:1208
LX200Telescope::SetFocuserSpeed
virtual bool SetFocuserSpeed(int speed) override
SetFocuserSpeed Set Focuser speed.
Definition: lx200telescope.cpp:1673
INDI::FocuserInterface::FOCUSER_HAS_VARIABLE_SPEED
@ FOCUSER_HAS_VARIABLE_SPEED
Definition: indifocuserinterface.h:79
INDI_UNUSED
#define INDI_UNUSED(x)
Definition: indidevapi.h:799
LX200Telescope::trackingMode
int trackingMode
Definition: lx200telescope.h:171
LX200_WEST
@ LX200_WEST
Definition: lx200driver.h:42
GUIDE_TAB
const char * GUIDE_TAB
GUIDE_TAB Where all the properties for guiding are located.
Definition: defaultdevice.cpp:42
LX200_GENERIC_SLEWRATE
#define LX200_GENERIC_SLEWRATE
Definition: lx200telescope.cpp:40
SITE_TAB
const char * SITE_TAB
SITE_TAB Where all site information setting are located.
Definition: defaultdevice.cpp:38
getLX200DEC
#define getLX200DEC(fd, x)
Definition: lx200driver.h:118
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
lx200driver.h
getSiteName
int getSiteName(int fd, char *siteName, int siteNum)
Definition: lx200driver.cpp:480
INDI::Telescope::MovementWES
ISwitch MovementWES[2]
Definition: inditelescope.h:745
LX200Telescope::isSlewComplete
virtual bool isSlewComplete()
Definition: lx200telescope.cpp:274
selectTrackingMode
int selectTrackingMode(int fd, int trackMode)
Definition: lx200driver.cpp:1790
FOCUS_TAB
const char * FOCUS_TAB
FOCUS_TAB Where all the properties for focuser are located.
Definition: defaultdevice.cpp:41
LX200Telescope::SiteNameT
IText SiteNameT[1]
Definition: lx200telescope.h:200
LX200Telescope::UsePulseCmdS
ISwitch UsePulseCmdS[2]
Definition: lx200telescope.h:191
INDI::GuiderInterface::initGuiderProperties
void initGuiderProperties(const char *deviceName, const char *groupName)
Initilize guider properties. It is recommended to call this function within initProperties() of your ...
Definition: indiguiderinterface.cpp:36
INDI::FocuserInterface::FOCUSER_CAN_ABORT
@ FOCUSER_CAN_ABORT
Definition: indifocuserinterface.h:76
getCalendarDate
int getCalendarDate(int fd, char *date)
Definition: lx200driver.cpp:398
LX200Telescope::currentDEC
double currentDEC
Definition: lx200telescope.h:178
IUFillText
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: indidriver.c:369
INDI::Telescope::EqNP
INumberVectorProperty EqNP
Definition: inditelescope.h:701
INDI::Telescope::m_Location
IGeographicCoordinates m_Location
Definition: inditelescope.h:648
ACK
#define ACK
Definition: stvdriver.h:35
LX200Telescope::MoveWE
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
Definition: lx200telescope.cpp:520
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
LX200Telescope::ReadScopeStatus
virtual bool ReadScopeStatus() override
Read telescope status.
Definition: lx200telescope.cpp:279
LX200_EAST
@ LX200_EAST
Definition: lx200driver.h:43
LX200Telescope::sendScopeLocation
virtual bool sendScopeLocation()
Definition: lx200telescope.cpp:1377
LX200Telescope::currentRA
double currentRA
Definition: lx200telescope.h:178
INDI::Telescope::TrackRateN
INumber TrackRateN[2]
Definition: inditelescope.h:851
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1442
LX200Telescope::Goto
virtual bool Goto(double ra, double dec) override
Move the scope to the supplied RA and DEC coordinates.
Definition: lx200telescope.cpp:327
INDI::Telescope::TrackState
TelescopeStatus TrackState
Definition: inditelescope.h:693
LX200Telescope::sendScopeTime
virtual bool sendScopeTime()
Definition: lx200telescope.cpp:1310
INDI::Telescope::TimeTP
ITextVectorProperty TimeTP
Definition: inditelescope.h:758
LX200Telescope::SiteS
ISwitch SiteS[4]
Definition: lx200telescope.h:196
INDI::Telescope::AbortSP
ISwitchVectorProperty AbortSP
Definition: inditelescope.h:710
LX200Telescope::getUTFOffset
virtual bool getUTFOffset(double *offset)
Definition: lx200telescope.cpp:1295
INDI::Telescope::SLEW_MAX
@ SLEW_MAX
Definition: inditelescope.h:91
LX200Telescope::debugTriggered
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
Definition: lx200telescope.cpp:47
LX200Telescope::GuideNorth
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
Definition: lx200telescope.cpp:1429
IUFindText
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition: indicom.c:1362
INDI::GuiderInterface::GuideNSNP
INumberVectorProperty GuideNSNP
Definition: indiguiderinterface.h:111
INDI::Telescope::TELESCOPE_HAS_TIME
@ TELESCOPE_HAS_TIME
Definition: inditelescope.h:163
LX200Telescope::updateLocation
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
Definition: lx200telescope.cpp:640
INDI::Telescope::SLEW_CENTERING
@ SLEW_CENTERING
Definition: inditelescope.h:89
setSiteLongitude
int setSiteLongitude(int fd, double CartographicLongitude)
Definition: lx200driver.cpp:1114
IEAddTimer
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.
Definition: eventloop.c:525
INDI::Telescope::LOCATION_ELEVATION
@ LOCATION_ELEVATION
Definition: inditelescope.h:119
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
LX200Telescope::MoveNS
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
Definition: lx200telescope.cpp:488
INDI::Telescope::TELESCOPE_HAS_LOCATION
@ TELESCOPE_HAS_LOCATION
Definition: inditelescope.h:164
LX200Telescope::LX200_HAS_FOCUS
@ LX200_HAS_FOCUS
Definition: lx200telescope.h:44
LX200Telescope::MoveFocuser
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser the focuser in a particular direction with a specific speed for a finite duration.
Definition: lx200telescope.cpp:1657
setFocuserSpeedMode
int setFocuserSpeedMode(int fd, int speedMode)
Definition: lx200driver.cpp:1303
LX200Telescope::updateFocusHelper
static void updateFocusHelper(void *p)
Definition: lx200telescope.cpp:996
_ITextVectorProperty::tp
IText * tp
Definition: indiapi.h:261
IUGetConfigText
int IUGetConfigText(const char *dev, const char *property, const char *member, char *value, int len)
IUGetConfigText Opens configuration file and reads single text property.
Definition: indidriver.c:1448
LX200Telescope::getLocalDate
virtual bool getLocalDate(char *dateString)
Definition: lx200telescope.cpp:1280
INDI::FocuserInterface::saveConfigItems
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
Definition: indifocuserinterface.cpp:596
INDI::IGeographicCoordinates::longitude
double longitude
Definition: libastro.h:66
ra
double ra
Definition: ieqprolegacydriver.cpp:43
LX200Telescope::sendLocationOnStartup
bool sendLocationOnStartup
Definition: lx200telescope.h:173
LX200Telescope::slewError
virtual void slewError(int slewCode)
Definition: lx200telescope.cpp:1218
IText
One text descriptor.
INDI::Telescope::TRACK_SIDEREAL
@ TRACK_SIDEREAL
Definition: inditelescope.h:95
INDI::IGeographicCoordinates::latitude
double latitude
Definition: libastro.h:67
INDI::FocuserInterface::FocusTimerNP
INumberVectorProperty FocusTimerNP
Definition: indifocuserinterface.h:278
LX200Telescope::GuideEast
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
Definition: lx200telescope.cpp:1507
INDI::DefaultDevice::getDriverInterface
virtual uint16_t getDriverInterface() override
Definition: defaultdevice.cpp:896
INDI::Telescope::TrackModeSP
ISwitchVectorProperty TrackModeSP
Definition: inditelescope.h:842
LOGF_WARN
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
LX200Telescope::targetRA
double targetRA
Definition: lx200telescope.h:177
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
INDI::Telescope::TelescopeMotionCommand
TelescopeMotionCommand
Definition: inditelescope.h:81
setLocalTime
#define setLocalTime(fd, x, y, z)
Definition: lx200driver.h:148
IUFillSwitchVector
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: indidriver.c:412
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
LX200_EQ_LONG_FORMAT
@ LX200_EQ_LONG_FORMAT
Definition: lx200driver.h:51
IUFillNumberVector
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: indidriver.c:455
LX200Telescope::GuideWETID
int GuideWETID
Definition: lx200telescope.h:165
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
abortSlew
int abortSlew(int fd)
Definition: lx200driver.cpp:1544
LX200Telescope::initProperties
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition: lx200telescope.cpp:64
_INumberVectorProperty::np
INumber * np
Definition: indiapi.h:334
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
LX200Telescope::AlignmentSP
ISwitchVectorProperty AlignmentSP
Definition: lx200telescope.h:182
INDI::Telescope::MOTION_START
@ MOTION_START
Definition: inditelescope.h:83
getLX200EquatorialFormat
int getLX200EquatorialFormat()
Definition: lx200driver.cpp:1688
INDI::FocuserInterface::processNumber
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
Definition: indifocuserinterface.cpp:168
LX200Telescope::LX200_HAS_TRACKING_FREQ
@ LX200_HAS_TRACKING_FREQ
Definition: lx200telescope.h:45
dec
double dec
Definition: ieqprolegacydriver.cpp:44
INDI::Telescope::MovementWESP
ISwitchVectorProperty MovementWESP
Definition: inditelescope.h:746
LX200Telescope::Handshake
virtual bool Handshake() override
perform handshake with device to check communication
Definition: lx200telescope.cpp:269
LX200Telescope::ISGetProperties
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: lx200telescope.cpp:161
LX200Telescope::JD
double JD
Definition: lx200telescope.h:176
getLX200RA
#define getLX200RA(fd, x)
Definition: lx200driver.h:117
LX200Telescope::guide_direction_ns
int8_t guide_direction_ns
Definition: lx200telescope.h:166
TRACKRATE_LUNAR
#define TRACKRATE_LUNAR
Definition: indicom.h:57
LX200Telescope::LX200_HAS_PULSE_GUIDING
@ LX200_HAS_PULSE_GUIDING
Definition: lx200telescope.h:48
INDI::FocuserInterface::FOCUSER_CAN_REVERSE
@ FOCUSER_CAN_REVERSE
Definition: indifocuserinterface.h:77
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::Telescope::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: inditelescope.cpp:770
LX200Telescope::getDefaultName
virtual const char * getDefaultName() override
Definition: lx200telescope.cpp:58
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
setObjectRA
int setObjectRA(int fd, double ra)
Definition: lx200driver.cpp:924
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
LX200Telescope::setLocalTime24
virtual bool setLocalTime24(uint8_t hour, uint8_t minute, uint8_t second)
Definition: lx200telescope.cpp:592
LX200Telescope::GuideSouth
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
Definition: lx200telescope.cpp:1468
getTrackFreq
int getTrackFreq(int fd, double *value)
Definition: lx200driver.cpp:703
LX200Telescope::AlignmentS
ISwitch AlignmentS[3]
Definition: lx200telescope.h:183
LX200Telescope::Park
virtual bool Park() override
Park the telescope to its home position.
Definition: lx200telescope.cpp:439
INDI::Telescope::SCOPE_TRACKING
@ SCOPE_TRACKING
Definition: inditelescope.h:77
MAXINDIFORMAT
#define MAXINDIFORMAT
Definition: indiapi.h:194
LX200Telescope::updateTime
virtual bool updateTime(ln_date *utc, double utc_offset) override
Update telescope time, date, and UTC offset.
Definition: lx200telescope.cpp:602
LX200Telescope
Definition: lx200telescope.h:34
LX200Telescope::timeFormat
int timeFormat
Definition: lx200telescope.h:169
LX200Telescope::guideTimeoutNS
void guideTimeoutNS()
Definition: lx200telescope.cpp:1616
INDI::Telescope::LOCATION_LATITUDE
@ LOCATION_LATITUDE
Definition: inditelescope.h:117
toggleTimeFormat
#define toggleTimeFormat(fd)
Definition: lx200driver.h:168
get_local_sidereal_time
double get_local_sidereal_time(double longitude)
get_local_sidereal_time Returns local sideral time given longitude and system clock.
INDI::Telescope::MovementNSS
ISwitch MovementNSS[2]
Definition: inditelescope.h:741
LX200Telescope::currentSiteNum
int currentSiteNum
Definition: lx200telescope.h:170
INDI::GuiderInterface::GuideWEN
INumber GuideWEN[2]
Definition: indiguiderinterface.h:112
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
LX200Telescope::GuideNSTID
int GuideNSTID
Definition: lx200telescope.h:164
INDI::Telescope::ISGetProperties
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: inditelescope.cpp:320
LX200Telescope::guideTimeoutWE
void guideTimeoutWE()
Definition: lx200telescope.cpp:1600
INDI::Telescope::TRACK_CUSTOM
@ TRACK_CUSTOM
Definition: inditelescope.h:98
getSiteLongitude
int getSiteLongitude(int fd, int *ddd, int *mm, double *ssf)
Definition: lx200driver.cpp:549
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
INDI::Telescope::SLEW_FIND
@ SLEW_FIND
Definition: inditelescope.h:90
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
LX200Telescope::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: lx200telescope.cpp:789
TRACKRATE_SOLAR
#define TRACKRATE_SOLAR
Definition: indicom.h:56
LX200Telescope::getAlignment
void getAlignment()
Definition: lx200telescope.cpp:1231
setCalenderDate
int setCalenderDate(int fd, int dd, int mm, int yy)
Definition: lx200driver.cpp:1047
IUSaveText
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indicom.c:1449
INDI::Telescope::TimeT
IText TimeT[2]
Definition: inditelescope.h:757
name
const char * name
Definition: indiserver.c:116
INDI::FocuserInterface::updateProperties
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
Definition: indifocuserinterface.cpp:101
LX200Telescope::LX200Telescope
LX200Telescope()
Definition: lx200telescope.cpp:43
setAlignmentMode
int setAlignmentMode(int fd, unsigned int alignMode)
Definition: lx200driver.cpp:1016
setPreciseTrackFreq
int setPreciseTrackFreq(int fd, double trackF)
Definition: lx200driver.cpp:1379
INDI::FocuserInterface::initProperties
void initProperties(const char *groupName)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
Definition: indifocuserinterface.cpp:35
INDI::Telescope::SetParked
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
Definition: inditelescope.cpp:1937
LX200_AM
@ LX200_AM
Definition: lx200driver.h:65
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
LX200Telescope::AbortFocuser
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: lx200telescope.cpp:1652
LX200_EQ_SHORT_FORMAT
@ LX200_EQ_SHORT_FORMAT
Definition: lx200driver.h:50
LX200_TRACK_MANUAL
@ LX200_TRACK_MANUAL
Definition: lx200driver.h:110
INDI::FocuserInterface::FocusReverseS
ISwitch FocusReverseS[2]
Definition: indifocuserinterface.h:303
INDI::Telescope::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: inditelescope.cpp:1029
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
INDI::DefaultDevice::saveConfig
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
Definition: defaultdevice.cpp:221
INDI::Telescope::SlewRateSP
ISwitchVectorProperty SlewRateSP
Definition: inditelescope.h:749
setTrackFreq
int setTrackFreq(int fd, double trackF)
Definition: lx200driver.cpp:1366
LX200Telescope::guideTimeoutHelperNS
static void guideTimeoutHelperNS(void *p)
Definition: lx200telescope.cpp:1590
AXIS_RA
@ AXIS_RA
Definition: indibasetypes.h:33
DIRECTION_WEST
@ DIRECTION_WEST
Definition: indibasetypes.h:51
INDI::Telescope::LOCATION_LONGITUDE
@ LOCATION_LONGITUDE
Definition: inditelescope.h:118
INDI::FocuserInterface::processSwitch
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
Definition: indifocuserinterface.cpp:414
TRACKRATE_SIDEREAL
#define TRACKRATE_SIDEREAL
Definition: indicom.h:54
setFocuserMotion
int setFocuserMotion(int fd, int motionType)
Definition: lx200driver.cpp:1276
setObjectDEC
int setObjectDEC(int fd, double dec)
Definition: lx200driver.cpp:959
fs_sexa
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string.
Definition: indicom.c:137
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
INDI::Telescope::MOTION_STOP
@ MOTION_STOP
Definition: inditelescope.h:84
LX200_SOUTH
@ LX200_SOUTH
Definition: lx200driver.h:44
LX200Telescope::TrackFreqNP
INumberVectorProperty TrackFreqNP
Definition: lx200telescope.h:186
checkLX200EquatorialFormat
int checkLX200EquatorialFormat(int fd)
Definition: lx200driver.cpp:1698
INDI::Telescope::AddTrackMode
virtual int AddTrackMode(const char *name, const char *label, bool isDefault=false)
AddTrackMode.
Definition: inditelescope.cpp:1676
LX200Telescope::LX200_HAS_ALIGNMENT_TYPE
@ LX200_HAS_ALIGNMENT_TYPE
Definition: lx200telescope.h:46
ISState
ISState
Switch state.
Definition: indiapi.h:148
getTimeFormat
int getTimeFormat(int fd, int *format)
Definition: lx200driver.cpp:438
INDI::Telescope::TRACK_SOLAR
@ TRACK_SOLAR
Definition: inditelescope.h:96
IUGetConfigOnSwitchIndex
int IUGetConfigOnSwitchIndex(const char *dev, const char *property, int *index)
IUGetConfigOnSwitchIndex Opens configuration file and reads single switch property to find ON switch ...
Definition: indidriver.c:1270
LX200Telescope::targetDEC
double targetDEC
Definition: lx200telescope.h:177
INDI::Telescope::PortFD
int PortFD
Definition: inditelescope.h:864
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1424
LX200Telescope::getDriverName
virtual const char * getDriverName() override
Definition: lx200telescope.cpp:53
INDI::Telescope::updateProperties
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: inditelescope.cpp:356
LX200Telescope::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: lx200telescope.cpp:699
Slew
int Slew(int fd)
Definition: lx200driver.cpp:1396
slewToPark
#define slewToPark(fd)
Definition: lx200driver.h:177
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
MoveTo
int MoveTo(int fd, int direction)
Definition: lx200driver.cpp:1432
LX200Telescope::ReverseFocuser
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition: lx200telescope.cpp:1646
LX200_24
@ LX200_24
Definition: lx200driver.h:64
INDI::GuiderInterface::GuideNSN
INumber GuideNSN[2]
Definition: indiguiderinterface.h:110
INDI::Telescope::GetTelescopeCapability
uint32_t GetTelescopeCapability() const
GetTelescopeCapability returns the capability of the Telescope.
Definition: inditelescope.h:186
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
check_lx200_connection
int check_lx200_connection(int fd)
Definition: lx200driver.cpp:176
INDI::Telescope::ParkSP
ISwitchVectorProperty ParkSP
Definition: inditelescope.h:722
INDI::Telescope::TRACK_LUNAR
@ TRACK_LUNAR
Definition: inditelescope.h:97
LX200Telescope::updateFocusTimer
void updateFocusTimer()
Definition: lx200telescope.cpp:1001
LX200Telescope::updateProperties
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: lx200telescope.cpp:199
LX200Telescope::SetTrackMode
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
Definition: lx200telescope.cpp:946
HaltMovement
int HaltMovement(int fd, int direction)
Definition: lx200driver.cpp:1500
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
LX200Telescope::SiteNameTP
ITextVectorProperty SiteNameTP
Definition: lx200telescope.h:199
LX200Telescope::TrackFreqN
INumber TrackFreqN[1]
Definition: lx200telescope.h:187
LX200Telescope::SendPulseCmd
virtual int SendPulseCmd(int8_t direction, uint32_t duration_msec)
Definition: lx200telescope.cpp:1585
INDI::DefaultDevice::setDriverInterface
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Definition: defaultdevice.cpp:902
IUFillSwitch
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: indidriver.c:320
AXIS_DE
@ AXIS_DE
Definition: indibasetypes.h:34
LX200Telescope::UsePulseCmdSP
ISwitchVectorProperty UsePulseCmdSP
Definition: lx200telescope.h:190
LX200Telescope::genericCapability
uint32_t genericCapability
Definition: lx200telescope.h:206
IERmTimer
void IERmTimer(int timerid)
Remove the timer with the given timerid, as returned from IEAddTimer() or IEAddPeriodicTimer().
Definition: eventloop.c:545
INDI::GuiderInterface::processGuiderProperties
void processGuiderProperties(const char *name, double values[], char *names[], int n)
Call this function whenever client updates GuideNSNP or GuideWSP properties in the primary device....
Definition: indiguiderinterface.cpp:49
INDI::FocuserInterface::FocusSpeedN
INumber FocusSpeedN[1]
Definition: indifocuserinterface.h:269
LX200Telescope::SiteSP
ISwitchVectorProperty SiteSP
Definition: lx200telescope.h:195
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151
INDI::FocuserInterface::FOCUS_OUTWARD
@ FOCUS_OUTWARD
Definition: indifocuserinterface.h:69