Instrument Neutral Distributed Interface INDI  1.9.5
lx200_10micron.cpp
Go to the documentation of this file.
1 /*
2  10micron INDI driver
3  GM1000HPS GM2000QCI GM2000HPS GM3000HPS GM4000QCI GM4000HPS AZ2000
4  Mount Command Protocol 2.14.11
5 
6  Copyright (C) 2017-2020 Hans Lambermont
7 
8  This library is free software; 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; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 
30 #include "lx200_10micron.h"
31 #include "indicom.h"
32 #include "lx200driver.h"
33 
34 #include <cstring>
35 #include <strings.h>
36 #include <termios.h>
37 #include <math.h>
38 #include <libnova.h>
39 
40 #define PRODUCT_TAB "Product"
41 #define ALIGNMENT_TAB "Alignment"
42 #define LX200_TIMEOUT 5 /* FD timeout in seconds */
43 
44 // INDI Number and Text names
45 #define REFRACTION_MODEL_TEMPERATURE "REFRACTION_MODEL_TEMPERATURE"
46 #define REFRACTION_MODEL_PRESSURE "REFRACTION_MODEL_PRESSURE"
47 #define MODEL_COUNT "MODEL_COUNT"
48 #define ALIGNMENT_POINTS "ALIGNMENT_POINTS"
49 #define ALIGNMENT_STATE "Alignment"
50 #define MINIMAL_NEW_ALIGNMENT_POINT_RO "MINIMAL_NEW_ALIGNMENT_POINT_RO"
51 #define MINIMAL_NEW_ALIGNMENT_POINT "MINIMAL_NEW_ALIGNMENT_POINT"
52 #define NEW_ALIGNMENT_POINT "NEW_ALIGNMENT_POINT"
53 #define NEW_ALIGNMENT_POINTS "NEW_ALIGNMENT_POINTS"
54 #define NEW_MODEL_NAME "NEW_MODEL_NAME"
55 #define PRODUCT_INFO "PRODUCT_INFO"
56 #define TLE_TEXT "TLE_TEXT"
57 #define TLE_NUMBER "TLE_NUMBER"
58 #define TRAJECTORY_TIME "TRAJECTORY_TIME"
59 #define SAT_TRACKING_STAT "SAT_TRACKING_STAT"
60 #define UNATTENDED_FLIP "UNATTENDED_FLIP"
61 
63 {
65 
78  );
79 
80  setVersion(1, 0);
81 }
82 
83 // Called by INDI::DefaultDevice::ISGetProperties
84 // Note that getDriverName calls ::getDefaultName which returns LX200 Generic
86 {
87  return "10micron";
88 }
89 
90 // Called by INDI::Telescope::callHandshake, either TCP Connect or Serial Port Connect
92 {
93  fd = PortFD;
94 
95  if (isSimulation() == true)
96  {
97  LOG_INFO("Simulate Connect.");
98  return true;
99  }
100 
101  // Set Ultra Precision Mode #:U2# , replies like 15:58:19.49 instead of 15:21.2
102  LOG_INFO("Setting Ultra Precision Mode.");
103  // #:U2#
104  // Set ultra precision mode. In ultra precision mode, extra decimal digits are returned for
105  // some commands, and there is no more difference between different emulation modes.
106  // Returns: nothing
107  // Available from version 2.10.
108  if (setCommandInt(fd, 2, "#:U") < 0)
109  {
110  LOG_ERROR("Failed to set Ultra Precision Mode.");
111  return false;
112  }
113 
114  return true;
115 }
116 
117 // Called only once by DefaultDevice::ISGetProperties
118 // Initialize basic properties that are required all the time
120 {
121  const bool result = LX200Generic::initProperties();
122  if (result)
123  {
124  // TODO initialize properties additional to INDI::Telescope
125  IUFillSwitch(&UnattendedFlipS[UNATTENDED_FLIP_DISABLED], "Disabled", "Disabled", ISS_ON);
128  UNATTENDED_FLIP, "Unattended Flip", MOTION_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
129 
130  IUFillNumber(&RefractionModelTemperatureN[0], "TEMPERATURE", "Celsius", "%+6.1f", -999.9, 999.9, 0, 0.);
133 
134  IUFillNumber(&RefractionModelPressureN[0], "PRESSURE", "hPa", "%6.1f", 0.0, 9999.9, 0, 0.);
137 
138  IUFillNumber(&ModelCountN[0], "COUNT", "#", "%.0f", 0, 999, 0, 0);
140  MODEL_COUNT, "Models", ALIGNMENT_TAB, IP_RO, 60, IPS_IDLE);
141 
142  IUFillNumber(&AlignmentPointsN[0], "COUNT", "#", "%.0f", 0, 100, 0, 0);
144  ALIGNMENT_POINTS, "Points", ALIGNMENT_TAB, IP_RO, 60, IPS_IDLE);
145 
146  IUFillSwitch(&AlignmentStateS[ALIGN_IDLE], "Idle", "Idle", ISS_ON);
147  IUFillSwitch(&AlignmentStateS[ALIGN_START], "Start", "Start new model", ISS_OFF);
148  IUFillSwitch(&AlignmentStateS[ALIGN_END], "End", "End new model", ISS_OFF);
149  IUFillSwitch(&AlignmentStateS[ALIGN_DELETE_CURRENT], "Del", "Delete current model", ISS_OFF);
152 
153  IUFillNumber(&MiniNewAlpRON[MALPRO_MRA], "MRA", "Mount RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
154  IUFillNumber(&MiniNewAlpRON[MALPRO_MDEC], "MDEC", "Mount DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
155  IUFillNumber(&MiniNewAlpRON[MALPRO_MSIDE], "MSIDE", "Pier Side (0=E 1=W)", "%.0f", 0, 1, 0, 0);
156  IUFillNumber(&MiniNewAlpRON[MALPRO_SIDTIME], "SIDTIME", "Sidereal Time (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
159 
160  IUFillNumber(&MiniNewAlpN[MALP_PRA], "PRA", "Solved RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
161  IUFillNumber(&MiniNewAlpN[MALP_PDEC], "PDEC", "Solved DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
164 
165  IUFillNumber(&NewAlpN[ALP_MRA], "MRA", "Mount RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
166  IUFillNumber(&NewAlpN[ALP_MDEC], "MDEC", "Mount DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
167  IUFillNumber(&NewAlpN[ALP_MSIDE], "MSIDE", "Pier Side (0=E 1=W)", "%.0f", 0, 1, 0, 0);
168  IUFillNumber(&NewAlpN[ALP_SIDTIME], "SIDTIME", "Sidereal Time (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
169  IUFillNumber(&NewAlpN[ALP_PRA], "PRA", "Solved RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
170  IUFillNumber(&NewAlpN[ALP_PDEC], "PDEC", "Solved DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
172  NEW_ALIGNMENT_POINT, "New Point", ALIGNMENT_TAB, IP_RW, 60, IPS_IDLE);
173 
174  IUFillNumber(&NewAlignmentPointsN[0], "COUNT", "#", "%.0f", 0, 100, 1, 0);
176  NEW_ALIGNMENT_POINTS, "New Points", ALIGNMENT_TAB, IP_RO, 60, IPS_IDLE);
177 
178  IUFillText(&NewModelNameT[0], "NAME", "Model Name", "newmodel");
180  NEW_MODEL_NAME, "New Name", ALIGNMENT_TAB, IP_RW, 60, IPS_IDLE);
181 
182  IUFillNumber(&TLEfromDatabaseN[0], "NUMBER", "#", "%.0f", 1, 999, 1, 1);
184  "TLE_NUMBER", "Database TLE ", SATELLITE_TAB, IP_RW, 60, IPS_IDLE);
185  }
186  return result;
187 }
188 
190 {
193  return true;
194 }
195 
196 // Called by INDI::Telescope when connected state changes to add/remove properties
198 {
199  bool result = LX200Generic::updateProperties();
200 
201  if (isConnected())
202  {
204  // getMountInfo defines ProductTP
216 
217  // read UnAttendedFlip setting from config and apply if available
218  int readit = 0;
219  for (int i = 0; readit == 0 && i < UnattendedFlipSP.nsp; i++)
220  {
222  }
223  if (readit == 0)
224  {
226  {
227  LOGF_INFO("Unattended Flip from config and mount are %s",
228  (UnattendedFlipS[UNATTENDED_FLIP_ENABLED].s == ISS_ON) ? "enabled" : "disabled");
229  }
230  else
231  {
232  LOGF_INFO("Read Unattended Flip %s from config while mount has %s, updating mount",
233  (UnattendedFlipS[UNATTENDED_FLIP_ENABLED].s == ISS_ON) ? "enabled" : "disabled",
234  (UnattendedFlip == UNATTENDED_FLIP_ENABLED) ? "enabled" : "disabled");
236  }
237  }
238  else
239  {
240  LOG_INFO("Did not find an Unattended Flip setting in the config file. Specify desired behaviour in Motion Control tab and save config in Options tab.");
241  }
242  }
243  else
244  {
258  }
259 
260  return result;
261 }
262 
263 // Called by LX200Generic::updateProperties
265 {
266  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "<%s>", __FUNCTION__);
267 
268  // cannot call LX200Generic::getBasicData(); as getTimeFormat :Gc# (and getSiteName :GM#) are not implemented on 10Micron
269  if (!isSimulation())
270  {
271  getMountInfo();
272 
273  getAlignment();
276 
277  if (getTrackFreq(PortFD, &TrackFreqN[0].value) < 0)
278  {
279  LOG_WARN("Failed to get tracking frequency from device.");
280  }
281  else
282  {
283  LOGF_INFO("Tracking frequency is %.1f Hz", TrackFreqN[0].value);
284  IDSetNumber(&TrackFreqNP, nullptr);
285  }
286 
287  char RefractionModelTemperature[80];
288  getCommandString(PortFD, RefractionModelTemperature, "#:GRTMP#");
289  float rmtemp;
290  sscanf(RefractionModelTemperature, "%f#", &rmtemp);
291  RefractionModelTemperatureN[0].value = rmtemp;
292  LOGF_INFO("RefractionModelTemperature is %0+6.1f degrees C", RefractionModelTemperatureN[0].value);
294 
295  char RefractionModelPressure[80];
296  getCommandString(PortFD, RefractionModelPressure, "#:GRPRS#");
297  float rmpres;
298  sscanf(RefractionModelPressure, "%f#", &rmpres);
299  RefractionModelPressureN[0].value = rmpres;
300  LOGF_INFO("RefractionModelPressure is %06.1f hPa", RefractionModelPressureN[0].value);
302 
303  int ModelCount;
304  getCommandInt(PortFD, &ModelCount, "#:modelcnt#");
305  ModelCountN[0].value = (double) ModelCount;
306  LOGF_INFO("%d Alignment Models", static_cast<int>(ModelCountN[0].value));
307  IDSetNumber(&ModelCountNP, nullptr);
308 
309  int AlignmentPoints;
310  getCommandInt(PortFD, &AlignmentPoints, "#:getalst#");
311  AlignmentPointsN[0].value = AlignmentPoints;
312  LOGF_INFO("%d Alignment Stars in active model", static_cast<int>(AlignmentPointsN[0].value));
313  IDSetNumber(&AlignmentPointsNP, nullptr);
314 
315  if (false == getUnattendedFlipSetting())
316  {
319  LOG_INFO("Unattended Flip is disabled.");
320  }
321  else
322  {
325  LOG_INFO("Unattended Flip is enabled.");
326  }
328  IDSetSwitch(&UnattendedFlipSP, nullptr);
329  }
330 
332  {
333  LOG_INFO("sendLocationOnStartup is enabled, call sendScopeLocation.");
335  }
336  else
337  {
338  LOG_INFO("sendLocationOnStartup is disabled, do not call sendScopeLocation.");
339  }
340  if (sendTimeOnStartup)
341  {
342  LOG_INFO("sendTimeOnStartup is enabled, call sendScopeTime.");
343  sendScopeTime();
344  }
345  else
346  {
347  LOG_INFO("sendTimeOnStartup is disabled, do not call sendScopeTime.");
348  }
349 }
350 
351 // Called by our getBasicData
352 bool LX200_10MICRON::getMountInfo()
353 {
354  char ProductName[80];
355  getCommandString(PortFD, ProductName, "#:GVP#");
356  char ControlBox[80];
357  getCommandString(PortFD, ControlBox, "#:GVZ#");
358  char FirmwareVersion[80];
359  getCommandString(PortFD, FirmwareVersion, "#:GVN#");
360  char FirmwareDate1[80];
361  getCommandString(PortFD, FirmwareDate1, "#:GVD#");
362  char FirmwareDate2[80];
363  char mon[4];
364  int dd, yyyy;
365  sscanf(FirmwareDate1, "%s %02d %04d", mon, &dd, &yyyy);
366  getCommandString(PortFD, FirmwareDate2, "#:GVT#");
367  char FirmwareDate[80];
368  snprintf(FirmwareDate, 80, "%04d-%02d-%02dT%s", yyyy, monthToNumber(mon), dd, FirmwareDate2);
369 
370  LOGF_INFO("Product:%s Control box:%s Firmware:%s of %s", ProductName, ControlBox, FirmwareVersion, FirmwareDate);
371 
372  IUFillText(&ProductT[PRODUCT_NAME], "NAME", "Product Name", ProductName);
373  IUFillText(&ProductT[PRODUCT_CONTROL_BOX], "CONTROL_BOX", "Control Box", ControlBox);
374  IUFillText(&ProductT[PRODUCT_FIRMWARE_VERSION], "FIRMWARE_VERSION", "Firmware Version", FirmwareVersion);
375  IUFillText(&ProductT[PRODUCT_FIRMWARE_DATE], "FIRMWARE_DATE", "Firmware Date", FirmwareDate);
377  PRODUCT_INFO, "Product", PRODUCT_TAB, IP_RO, 60, IPS_IDLE);
378 
380 
381  return true;
382 }
383 
384 // INDI::Telescope calls ReadScopeStatus() every POLLMS to check the link to the telescope and update its state and position.
385 // The child class should call newRaDec() whenever a new value is read from the telescope.
387 {
388  if (!isConnected())
389  {
390  return false;
391  }
392  if (isSimulation())
393  {
394  mountSim();
395  return true;
396  }
397 
398  // Read scope status, based loosely on LX200_GENERIC::getCommandString
399  // #:Ginfo#
400  // Get multiple information. Returns a string where multiple data are encoded, separated
401  // by commas ',', and terminated by '#'. Data are recognized by their position in the string.
402  // The data are the following:
403  // Position Datum
404  // 1 The telescope right ascension in hours and decimals (from 000.00000 to 23.99999),
405  // true equinox and equator of date of observation (i.e. Jnow).
406  // 2 The telescope declination in degrees and decimals (from –90.0000 to +90.0000),
407  // true equinox and equator of date of observation (i.e. Jnow).
408  // 3 A flag indicating the side of the pier on which the telescope is currently positioned
409  // ("E" or "W").
410  // 4 The telescope azimuth in degrees and decimals (from 000.0000 to 359.9999).
411  // 5 The telescope altitude in degrees and decimals (from -90.0000 to +90.0000).
412  // 6 The julian date (JJJJJJJ.JJJJJJJJ), UTC, with leap second flag (see command
413  // :GJD2# for the description of this datum).
414  // 7 A number encoding the status of the mount as in the :Gstat command.
415  // 8 A number returning the slew status (0 if :D# would return no slew, 1 otherwise).
416  // The string is terminated by '#'. Other parameters may be added in future at the end of
417  // the string: do not assume that the number of parameters will stay the same.
418  // Available from version 2.14.9 (previous versions may have this command but it was
419  // experimental and possibly with a different format).
420  char cmd[] = "#:Ginfo#";
421  char data[80];
422  char *term;
423  int error_type;
424  int nbytes_write = 0, nbytes_read = 0;
425  // DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s>", cmd);
426  if ((error_type = tty_write_string(fd, cmd, &nbytes_write)) != TTY_OK)
427  {
428  return false;
429  }
430  error_type = tty_read_section(fd, data, '#', LX200_TIMEOUT, &nbytes_read);
431  tcflush(fd, TCIFLUSH);
432  if (error_type != TTY_OK)
433  {
434  return false;
435  }
436  term = strchr(data, '#');
437  if (term)
438  {
439  *(term + 1) = '\0';
440  }
441  else
442  {
443  return false;
444  }
445  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s> RES <%s>", cmd, data);
446 
447  // TODO: check if this needs changing when satellite tracking
448  // Now parse the data. This format may consist of more parts some day
449  nbytes_read = sscanf(data, "%g,%g,%c,%g,%g,%g,%d,%d#", &Ginfo.RA_JNOW, &Ginfo.DEC_JNOW, &Ginfo.SideOfPier,
450  &Ginfo.AZ, &Ginfo.ALT, &Ginfo.Jdate, &Ginfo.Gstat, &Ginfo.SlewStatus);
451  if (nbytes_read < 0)
452  {
453  return false;
454  }
455 
456  if (Ginfo.Gstat != OldGstat)
457  {
458  if (OldGstat != GSTAT_UNSET)
459  {
460  LOGF_INFO("Gstat changed from %d to %d", OldGstat, Ginfo.Gstat);
461  }
462  else
463  {
464  LOGF_INFO("Gstat initialized at %d", Ginfo.Gstat);
465  }
466  }
467  switch (Ginfo.Gstat)
468  {
469  case GSTAT_TRACKING:
471  break;
472  case GSTAT_STOPPED:
474  break;
475  case GSTAT_PARKING:
477  break;
478  case GSTAT_UNPARKING:
480  break;
483  break;
484  case GSTAT_PARKED:
486  if (!isParked())
487  SetParked(true);
488  break;
491  break;
494  break;
497  break;
500  break;
503  break;
504  case GSTAT_NEED_USEROK:
506  break;
509  break;
510  case GSTAT_ERROR:
512  break;
513  default:
514  return false;
515  }
516  setPierSide((toupper(Ginfo.SideOfPier) == 'E') ? INDI::Telescope::PIER_EAST : INDI::Telescope::PIER_WEST);
517 
518  OldGstat = Ginfo.Gstat;
519  NewRaDec(Ginfo.RA_JNOW, Ginfo.DEC_JNOW);
520 
521  // Update alignment Mini new alignment point Read-Only fields
522  char LocalSiderealTimeS[80];
523  getCommandString(fd, LocalSiderealTimeS, "#:GS#");
524  f_scansexa(LocalSiderealTimeS, &Ginfo.SiderealTime);
525  MiniNewAlpRON[MALPRO_MRA].value = Ginfo.RA_JNOW;
526  MiniNewAlpRON[MALPRO_MDEC].value = Ginfo.DEC_JNOW;
527  MiniNewAlpRON[MALPRO_MSIDE].value = (toupper(Ginfo.SideOfPier) == 'E') ? 0 : 1;
528  MiniNewAlpRON[MALPRO_SIDTIME].value = Ginfo.SiderealTime;
529  IDSetNumber(&MiniNewAlpRONP, nullptr);
530 
531  return true;
532 }
533 
535 {
536  // #:KA#
537  // Slew to park position
538  // Returns: nothing
539  LOG_INFO("Parking.");
540  if (setStandardProcedureWithoutRead(fd, "#:KA#") < 0)
541  {
542  return false;
543  }
544 
546  // postpone SetParked(true) for ReadScopeStatus so that we know it is actually correct
547  return true;
548 }
549 
551 {
552  // #:PO#
553  // Unpark
554  // Returns:nothing
555  LOG_INFO("Unparking.");
556  if (setStandardProcedureWithoutRead(fd, "#:PO#") < 0)
557  {
558  return false;
559  }
560 
562  SetParked(false);
563  return true;
564 }
565 
567 {
568  // #:Guaf#
569  // Returns the unattended flip setting.
570  // Returns:
571  // 0 disabled
572  // 1 enabled
573  // Available from version 2.11.
574  // Note: unattended flip didn't work properly in firmware versions up to 2.13.8 included.
575  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "<%s>", __FUNCTION__);
576  char guaf[80];
577  getCommandString(PortFD, guaf, "#:Guaf#");
578  if ('1' == guaf[0])
579  {
581  }
582  else
583  {
585  }
586  return '1' == guaf[0];
587 }
588 
590 {
591  // #:SuafN#
592  // Enables or disables the unattended flip. Use N=1 to enable, N=0 to disable. This is set always to 0 after power up.
593  // Returns: nothing
594  // Available from version 2.11.
595  // unattended flip didn't work properly in firmware versions up to 2.13.8 included.
596  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "<%s>", __FUNCTION__);
597  char data[64];
598  snprintf(data, sizeof(data), "#:Suaf%d#", (setting == false) ? 0 : 1);
599  if (0 == setStandardProcedureWithoutRead(fd, data))
600  {
601  if (setting == false)
602  {
604  }
605  else
606  {
608  }
609  return true;
610  }
611  return false;
612 }
613 
615 {
616  // #:FLIP#
617  // This command acts in different ways on the AZ2000 and german equatorial (GM1000 – GM4000) mounts.
618  // On an AZ2000 mount: When observing an object near the lowest culmination, requests to make a 360° turn of the azimuth axis and point the object again.
619  // On a german equatorial mount: When observing an object near the meridian, requests to make a 180° turn of the RA axis and move the declination axis in order to
620  // point the object with the telescope on the other side of the mount.
621  // Returns:
622  // 1 if successful
623  // 0 if the movement cannot be done
624  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "<%s>", __FUNCTION__);
625  char data[64];
626  snprintf(data, sizeof(data), "#:FLIP#");
627  return 0 == setStandardProcedureAndExpect(fd, data, "1");
628 }
629 
631 {
632  // #:CMCFGn#
633  // Configures the behaviour of the :CM# and :CMR# commands depending on the value
634  // of n. If n=0, :the commands :CM# and :CMR# work in the default mode, i.e. they
635  // synchronize the position ot the mount with the coordinates of the currently selected
636  // target by correcting the axis offset values. If n=1, the commands :CM# and :CMR#
637  // work by using the synchronization position as an additional alignment star for refining
638  // the alignment model.
639  // Returns:
640  // the string "0#" if the value 0 has been passed
641  // the string "1#" if the value 1 has been passed
642  // Available from version 2.8.15.
643  LOG_INFO("SyncConfig.");
644  if (setCommandInt(fd, cmcfg, "#:CMCFG") < 0)
645  {
646  return false;
647  }
648  return true;
649 }
650 
651 bool LX200_10MICRON::setLocalDate(uint8_t days, uint8_t months, uint16_t years)
652 {
653  // #:SCYYYY-MM-DD#
654  // Set date to YYYY-MM-DD (year, month, day). The date is expressed in local time.
655  // Returns:
656  // 0 if the date is invalid
657  // The character "1" without additional strings in ultra-precision mode (regardless of
658  // emulation).
659  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "<%s>", __FUNCTION__);
660  char data[64];
661  snprintf(data, sizeof(data), ":SC%04d-%02d-%02d#", years, months, days);
662  return 0 == setStandardProcedureAndExpect(fd, data, "1");
663 }
664 
665 bool LX200_10MICRON::SetTLEtoFollow(const char *tle)
666 {
667  // #:TLEL0<two line element>#
668  // Loads satellite orbital elements in two-line format directly from the command protocol.
669  // <two line element> is a string containing the two line elements. Each lines can be
670  // terminated by escaped newline (ASCII code 10), carriage return (ASCII code 13) or a
671  // combination of both. The first line may contain the satellite name. The entire string is
672  // escaped with the mechanism described in the "escaped strings" section below.
673  // The TLE format is described here:
674  // https://www.celestrak.com/NORAD/documentation/tle-fmt.asp
675  // For example, loading the NOAA 14 element set of that page can be accomplished with:
676  // :TLEL0NOAA·14·················$0a
677  // 1·23455U·94089A···97320.90946019··.00000140··00000-0··10191-3·0··2621$0a
678  // 2·23455··99.0090·272.6745·0008546·223.1686·136.8816·14.11711747148495#
679  // Returns:
680  // E# invalid format
681  // V# valid format
682  // Available from version 2.13.20.
683  LOGF_INFO("The function is called with TLE %s", tle);
684  if (strlen(tle) > 230)
685  {
686  LOG_WARN("TLE is too long");
687  }
688 
689  std::string tle_str;
690  std::string sep = "$0a";
691  std::string search = "\n";
692  tle_str = (std::string) tle;
693  for( size_t pos = 0; ; pos += sep.length() )
694  {
695  // Locate the substring to replace
696  pos = tle_str.find( search, pos );
697  if( pos == std::string::npos ) break;
698  // Replace by erasing and inserting
699  tle_str.erase( pos, search.length() );
700  tle_str.insert( pos, sep );
701  }
702  char command[250];
703  snprintf(command, sizeof(command), ":TLEL0%s#", tle_str.c_str());
704 
705  if ( !isSimulation() )
706  {
707  LOG_INFO(command);
708  char response[2];
709  if (0 != setStandardProcedureAndReturnResponse(fd, command, response, 2) )
710  {
711  LOG_ERROR("TLE set error");
712  return 1;
713  }
714  if (response[0] == 'E')
715  {
716  LOG_ERROR("Invalid formatting of TLE, trying to split:");
717  char *pch = strtok ((char*) tle, "\n");
718  while (pch != nullptr)
719  {
720  LOGF_INFO("%s\n", pch);
721  pch = strtok (nullptr, "\n");
722  }
723  return 1;
724  }
725  }
726  else
727  {
728  char *pch = strtok ((char*) tle, "\n");
729  while (pch != nullptr)
730  {
731  LOGF_INFO("%s\n", pch);
732  pch = strtok (nullptr, "\n");
733  }
734  }
735  return 0;
736 }
737 
739 {
740  // #:TLEDLn#
741  // Loads orbital elements for a satellite from the TLE database in the mount. n is the index of the
742  // orbital elements in the database, starting from 1 to the number returned by the TLEDN command.
743  // Returns:
744  // E# the mount database doesn't contain a TLE with the given index.
745  // <two line elements># an escaped string containing the TLE data from the mount
746  // database which has been loaded. Lines are terminated by ASCII newline (ASCII code 10).
747  // Available from version 2.13.20.
748  char command[12];
749  snprintf(command, sizeof(command), ":TLEDL%d#", tleN);
750 
751  LOG_INFO("Setting TLE from Database");
752  if ( !isSimulation() )
753  {
754  LOG_INFO(command);
755  char response[210];
756  if (0 != setStandardProcedureAndReturnResponse(fd, command, response, 210) )
757  {
758  LOG_ERROR("TLE set error");
759  return 1;
760  }
761  if (response[0] == 'E')
762  {
763  LOG_ERROR("TLE number not in mount");
764  return 1;
765  }
766  }
767  return 0;
768 }
769 
770 bool LX200_10MICRON::CalculateSatTrajectory(std::string start_pass_isodatetime, std::string end_pass_isodatetime)
771 {
772  // #:TLEPJD,min#
773  // Precalulates the first transit of the satellite with the currently loaded orbital elements,
774  // starting from Julian Date JD and for a period of min minutes, where min is from 1 to 1440.
775  // Two-line elements have to be loaded with the :TLEL command.
776  // Returns:
777  // E# no TLE loaded or invalid command
778  // N# no passes in the given amount of time
779  // JDstart,JDend,flags# data for the first pass in the given interval. JDstart and JDend
780  // mark the beginning and the end of the given transit. Flags is a string which can be
781  // empty or contain the letter F – meaning that mount will flip during the transit.
782  // Available from version 2.13.20.
783  struct ln_date start_pass;
784  if (extractISOTime(start_pass_isodatetime.c_str(), &start_pass) == -1)
785  {
786  LOGF_ERROR("Date/Time is invalid: %s.", start_pass_isodatetime.c_str());
787  return 1;
788  }
789 
790  struct ln_date end_pass;
791  if (extractISOTime(end_pass_isodatetime.c_str(), &end_pass) == -1)
792  {
793  LOGF_ERROR("Date/Time is invalid: %s.", end_pass_isodatetime.c_str());
794  return 1;
795  }
796 
797  double JD_start;
798  double JD_end;
799  JD_start = ln_get_julian_day(&start_pass);
800  JD_end = ln_get_julian_day(&end_pass);
801  int nextPassInMinutes = static_cast<int>(ceil((JD_end - JD_start) * 24 * 60));
802  int nextPassinMinutesUpTo1440 = std::min(nextPassInMinutes, 1440);
803  int nextPassinMinutesBetween1and1440 = std::max(nextPassinMinutesUpTo1440, 1);
804 
805  char command[28];
806  snprintf(command, sizeof(command), ":TLEP%7.8f,%01d#", JD_start, nextPassinMinutesBetween1and1440);
807  LOGF_INFO("Julian day %7.8f", JD_start);
808  LOGF_INFO("For the next %01d minutes", nextPassinMinutesBetween1and1440);
809  LOGF_INFO("Command: %s", command);
810  if ( !isSimulation() )
811  {
812  LOG_INFO(command);
813  char response[36];
814  if (0 != setStandardProcedureAndReturnResponse(fd, command, response, 36) )
815  {
816  LOG_ERROR("TLE calculate error");
817  return 1;
818  }
819  if (response[0] == 'E')
820  {
821  LOG_ERROR("TLE not loaded or invalid command");
822  return 1;
823  }
824  if (response[0] == 'N')
825  {
826  LOG_ERROR("No passes loaded");
827  return 1;
828  }
829  }
830  return 0;
831 }
832 
834 {
835  // #:TLES#
836  // Slews to the start of the satellite transit that has been precalculated with the :TLEP command.
837  // Returns:
838  // E# no transit has been precalculated
839  // F# slew failed due to mount parked or other status blocking slews
840  // V# slewing to the start of the transit, the mount will automatically start tracking the satellite.
841  // S# the transit has already started, slewing to catch the satellite
842  // Q# the transit has already ended, no slew occurs
843  // Available from version 2.13.20.
844  char command[7];
845  snprintf(command, sizeof(command), ":TLES#");
846  if ( !isSimulation() )
847  {
848  LOG_INFO(command);
849  char response[2];
850  if (0 != setStandardProcedureAndReturnResponse(fd, command, response, 2) )
851  {
852  LOG_ERROR("TLE track error");
853  return 1;
854  }
855  if (response[0] == 'E')
856  {
857  LOG_ERROR("TLE transit not calculated");
858  return 2;
859  }
860  if (response[0] == 'F')
861  {
862  LOG_ERROR("Slew failed");
863  return 3;
864  }
865  if (response[0] == 'V')
866  {
867  LOG_INFO("Slewing to start of transit");
868  return 0;
869  }
870  if (response[0] == 'S')
871  {
872  LOG_INFO("Slewing to transiting satellite");
873  return 0;
874  }
875  if (response[0] == 'Q')
876  {
877  LOG_ERROR("Transit is already over");
878  return 4;
879  }
880  }
881  return 0;
882 }
883 
885 {
886  // #:SRTMPsTTT.T#
887  // Sets the temperature used in the refraction model to sTTT.T degrees Celsius (°C).
888  // Returns:
889  // 0 invalid
890  // 1 valid
891  // Available from version 2.3.0.
892  char data[16];
893  snprintf(data, 16, "#:SRTMP%0+6.1f#", temperature);
894  return setStandardProcedure(fd, data);
895 }
896 
898 {
899  // #:SRPRSPPPP.P#
900  // Sets the atmospheric pressure used in the refraction model to PPPP.P hPa. Note
901  // that this is the pressure at the location of the telescope, and not the pressure at sea level.
902  // Returns:
903  // 0 invalid
904  // 1 valid
905  // Available from version 2.3.0.
906  char data[16];
907  snprintf(data, 16, "#:SRPRS%06.1f#", pressure);
908  return setStandardProcedure(fd, data);
909 }
910 
911 int LX200_10MICRON::AddSyncPoint(double MRa, double MDec, double MSide, double PRa, double PDec, double SidTime)
912 {
913  // #:newalptMRA,MDEC,MSIDE,PRA,PDEC,SIDTIME#
914  // Add a new point to the alignment specification. The parameters are:
915  // MRA – the mount-reported right ascension, expressed as HH:MM:SS.S
916  // MDEC – the mount-reported declination, expressed as sDD:MM:SS
917  // MSIDE – the mount-reported pier side (the letter 'E' or 'W', as reported by the :pS# command)
918  // PRA – the plate-solved right ascension (i.e. the right ascension the telescope was
919  // effectively pointing to), expressed as HH:MM:SS.S
920  // PDEC – the plate-solved declination (i.e. the declination the telescope was effectively
921  // pointing to), expressed as sDD:MM:SS
922  // SIDTIME – the local sidereal time at the time of the measurement of the point,
923  // expressed as HH:MM:SS.S
924  // Returns:
925  // the string "nnn#" if the point is valid, where nnn is the current number of points in the
926  // alignment specification (including this one)
927  // the string "E#" if the point is not valid
928  // See also the paragraph Entering an alignment model.
929  // Available from version 2.8.15.
930  char MRa_str[32], MDec_str[32];
931  fs_sexa(MRa_str, MRa, 0, 36000);
932  fs_sexa(MDec_str, MDec, 0, 3600);
933 
934  char MSide_char;
935  (static_cast<int>(MSide) == 0) ? MSide_char = 'E' : MSide_char = 'W';
936 
937  char PRa_str[32], PDec_str[32];
938  fs_sexa(PRa_str, PRa, 0, 36000);
939  fs_sexa(PDec_str, PDec, 0, 3600);
940 
941  char SidTime_str[32];
942  fs_sexa(SidTime_str, SidTime, 0, 36000);
943 
944  char command[80];
945  snprintf(command, 80, "#:newalpt%s,%s,%c,%s,%s,%s#", MRa_str, MDec_str, MSide_char, PRa_str, PDec_str, SidTime_str);
946  LOGF_INFO("AddSyncPoint %s", command);
947 
948  char response[6];
949  if (0 != setStandardProcedureAndReturnResponse(fd, command, response, 5) || response[0] == 'E')
950  {
951  LOG_ERROR("AddSyncPoint error");
952  return 1;
953  }
954  response[4] = 0;
955  int points;
956  int nbytes_read = sscanf(response, "%3d#", &points);
957  if (nbytes_read < 0)
958  {
959  LOGF_ERROR("AddSyncPoint response error %d", nbytes_read);
960  return 1;
961  }
962  LOGF_INFO("AddSyncPoint responded [%4s], there are now %d new alignment points", response, points);
963  NewAlignmentPointsN[0].value = points;
965 
966  return 0;
967 }
968 
969 int LX200_10MICRON::AddSyncPointHere(double PRa, double PDec)
970 {
971  double MSide = (toupper(Ginfo.SideOfPier) == 'E') ? 0 : 1;
972  return AddSyncPoint(Ginfo.RA_JNOW, Ginfo.DEC_JNOW, MSide, PRa, PDec, Ginfo.SiderealTime);
973 }
974 
975 bool LX200_10MICRON::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
976 {
977  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
978  {
979  if (strcmp(name, REFRACTION_MODEL_TEMPERATURE) == 0)
980  {
981  IUUpdateNumber(&RefractionModelTemperatureNP, values, names, n);
983  {
984  LOG_ERROR("SetRefractionModelTemperature error");
987  return false;
988  }
991  LOGF_INFO("RefractionModelTemperature set to %0+6.1f degrees C", RefractionModelTemperatureN[0].value);
992  return true;
993  }
994  if (strcmp(name, REFRACTION_MODEL_PRESSURE) == 0)
995  {
996  IUUpdateNumber(&RefractionModelPressureNP, values, names, n);
998  {
999  LOG_ERROR("SetRefractionModelPressure error");
1002  return false;
1003  }
1006  LOGF_INFO("RefractionModelPressure set to %06.1f hPa", RefractionModelPressureN[0].value);
1007  return true;
1008  }
1009  if (strcmp(name, MODEL_COUNT) == 0)
1010  {
1011  IUUpdateNumber(&ModelCountNP, values, names, n);
1012  ModelCountNP.s = IPS_OK;
1013  IDSetNumber(&ModelCountNP, nullptr);
1014  LOGF_INFO("ModelCount %d", ModelCountN[0].value);
1015  return true;
1016  }
1017  if (strcmp(name, MINIMAL_NEW_ALIGNMENT_POINT_RO) == 0)
1018  {
1019  IUUpdateNumber(&MiniNewAlpNP, values, names, n);
1021  IDSetNumber(&MiniNewAlpRONP, nullptr);
1022  return true;
1023  }
1024  if (strcmp(name, MINIMAL_NEW_ALIGNMENT_POINT) == 0)
1025  {
1026  if (AlignmentState != ALIGN_START)
1027  {
1028  LOG_ERROR("Cannot add alignment points yet, need to start a new alignment first");
1029  return false;
1030  }
1031 
1032  IUUpdateNumber(&MiniNewAlpNP, values, names, n);
1033  if (0 != AddSyncPointHere(MiniNewAlpN[MALP_PRA].value, MiniNewAlpN[MALP_PDEC].value))
1034  {
1035  LOG_ERROR("AddSyncPointHere error");
1037  IDSetNumber(&MiniNewAlpNP, nullptr);
1038  return false;
1039  }
1040  MiniNewAlpNP.s = IPS_OK;
1041  IDSetNumber(&MiniNewAlpNP, nullptr);
1042  return true;
1043  }
1044  if (strcmp(name, NEW_ALIGNMENT_POINT) == 0)
1045  {
1046  if (AlignmentState != ALIGN_START)
1047  {
1048  LOG_ERROR("Cannot add alignment points yet, need to start a new alignment first");
1049  return false;
1050  }
1051 
1052  IUUpdateNumber(&NewAlpNP, values, names, n);
1053  if (0 != AddSyncPoint(NewAlpN[ALP_MRA].value, NewAlpN[ALP_MDEC].value, NewAlpN[ALP_MSIDE].value,
1054  NewAlpN[ALP_PRA].value, NewAlpN[ALP_PDEC].value, NewAlpN[ALP_SIDTIME].value))
1055  {
1056  LOG_ERROR("AddSyncPoint error");
1057  NewAlpNP.s = IPS_ALERT;
1058  IDSetNumber(&NewAlpNP, nullptr);
1059  return false;
1060  }
1061  NewAlpNP.s = IPS_OK;
1062  IDSetNumber(&NewAlpNP, nullptr);
1063  return true;
1064  }
1065  if (strcmp(name, NEW_ALIGNMENT_POINTS) == 0)
1066  {
1067  IUUpdateNumber(&NewAlignmentPointsNP, values, names, n);
1069  IDSetNumber(&NewAlignmentPointsNP, nullptr);
1070  LOGF_INFO("New unnamed Model now has %d alignment points", NewAlignmentPointsN[0].value);
1071  return true;
1072  }
1073  if (strcmp(name, "TLE_NUMBER") == 0)
1074  {
1075  LOG_INFO("I am trying to set from Database");
1076 
1077  IUUpdateNumber(&TLEfromDatabaseNP, values, names, n);
1078  if ( 0 != SetTLEfromDatabase(TLEfromDatabaseN[0].value) )
1079  {
1081  IDSetNumber(&TLEfromDatabaseNP, nullptr);
1082  return false;
1083  }
1086  IDSetText(&TLEtoTrackTP, nullptr);
1087  IDSetNumber(&TLEfromDatabaseNP, nullptr);
1088  LOGF_INFO("Selected TLE nr %.0f from database", TLEfromDatabaseN[0].value);
1089 
1090  return true;
1091  }
1092  }
1093 
1094  // Let INDI::LX200Generic handle any other number properties
1095  return LX200Generic::ISNewNumber(dev, name, values, names, n);
1096 }
1097 
1098 bool LX200_10MICRON::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
1099 {
1100  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
1101  {
1102  if (strcmp(AlignmentStateSP.name, name) == 0)
1103  {
1104  IUUpdateSwitch(&AlignmentStateSP, states, names, n);
1105  int index = IUFindOnSwitchIndex(&AlignmentStateSP);
1106 
1107  switch (index)
1108  {
1109  case ALIGN_IDLE:
1110  AlignmentState = ALIGN_IDLE;
1111  LOG_INFO("Alignment state is IDLE");
1112  break;
1113 
1114  case ALIGN_START:
1115  // #:newalig#
1116  // Start creating a new alignment specification, that will be entered with the :newalpt command.
1117  // Returns:
1118  // the string "V#" (this is always successful).
1119  // Available from version 2.8.15.
1120  if (0 != setStandardProcedureAndExpect(fd, "#:newalig#", "V"))
1121  {
1122  LOG_ERROR("New alignment start error");
1124  IDSetSwitch(&AlignmentStateSP, nullptr);
1125  return false;
1126  }
1127  LOG_INFO("New Alignment started");
1128  AlignmentState = ALIGN_START;
1129  break;
1130 
1131  case ALIGN_END:
1132  // #:endalig#
1133  // Completes the alignment specification and computes a new alignment from the given
1134  // alignment points.
1135  // Returns:
1136  // the string "V#" if the alignment has been computed successfully
1137  // the string "E#" if the alignment couldn't be computed successfully with the current
1138  // alignment specification. In this case the previous alignment is retained.
1139  // Available from version 2.8.15.
1140  if (0 != setStandardProcedureAndExpect(fd, "#:endalig#", "V"))
1141  {
1142  LOG_ERROR("New alignment end error");
1144  IDSetSwitch(&AlignmentStateSP, nullptr);
1145  return false;
1146  }
1147  LOG_INFO("New Alignment ended");
1148  AlignmentState = ALIGN_END;
1149  break;
1150 
1151  case ALIGN_DELETE_CURRENT:
1152  // #:delalig#
1153  // Deletes the current alignment model and stars.
1154  // Returns: an empty string terminated by '#'.
1155  // Available from version 2.8.15.
1156  if (0 != setStandardProcedureAndExpect(fd, "#:delalig#", "#"))
1157  {
1158  LOG_ERROR("Delete current alignment error");
1160  IDSetSwitch(&AlignmentStateSP, nullptr);
1161  return false;
1162  }
1163  LOG_INFO("Current Alignment deleted");
1164  AlignmentState = ALIGN_DELETE_CURRENT;
1165  break;
1166 
1167  default:
1169  IDSetSwitch(&AlignmentStateSP, "Unknown alignment index %d", index);
1170  AlignmentState = ALIGN_IDLE;
1171  return false;
1172  }
1173 
1175  IDSetSwitch(&AlignmentStateSP, nullptr);
1176  return true;
1177  }
1178  if (strcmp(TrackSatSP.name, name) == 0)
1179  {
1180 
1181  IUUpdateSwitch(&TrackSatSP, states, names, n);
1182  int index = IUFindOnSwitchIndex(&TrackSatSP);
1183 
1184  switch (index)
1185  {
1186  case SAT_TRACK:
1187  if ( 0 != TrackSat() )
1188  {
1190  IDSetSwitch(&TrackSatSP, nullptr);
1191  LOG_ERROR("Tracking failed");
1192  return false;
1193  }
1194  TrackSatSP.s = IPS_OK;
1195  IDSetSwitch(&TrackSatSP, nullptr);
1196  LOG_INFO("Tracking satellite");
1197  return true;
1198  case SAT_HALT:
1199  if ( !Abort() )
1200  {
1202  IDSetSwitch(&TrackSatSP, nullptr);
1203  LOG_ERROR("Halt failed");
1204  return false;
1205  }
1206  TrackSatSP.s = IPS_OK;
1207  IDSetSwitch(&TrackSatSP, nullptr);
1208  LOG_INFO("Halt tracking");
1209  return true;
1210  default:
1212  IDSetSwitch(&TrackSatSP, "Unknown tracking modus %d", index);
1213  return false;
1214  }
1215  }
1216 
1217  if (strcmp(UnattendedFlipSP.name, name) == 0)
1218  {
1219  IUUpdateSwitch(&UnattendedFlipSP, states, names, n);
1220  int index = IUFindOnSwitchIndex(&UnattendedFlipSP);
1221  switch (index)
1222  {
1224  if (false == setUnattendedFlipSetting(false))
1225  {
1226  LOG_ERROR("Setting unattended flip failed");
1228  IDSetSwitch(&UnattendedFlipSP, nullptr);
1229  return false;
1230  }
1231  LOG_INFO("Unattended flip disabled");
1232  break;
1234  if (false == setUnattendedFlipSetting(true))
1235  {
1236  LOG_ERROR("Setting unattended flip failed");
1238  IDSetSwitch(&UnattendedFlipSP, nullptr);
1239  return false;
1240  }
1241  LOG_INFO("Unattended flip enabled");
1242  break;
1243  default:
1245  IDSetSwitch(&UnattendedFlipSP, "Unknown unattended flip setting %d", index);
1246  return false;
1247  }
1249  IDSetSwitch(&UnattendedFlipSP, nullptr);
1250  return true;
1251  }
1252  }
1253 
1254  return LX200Generic::ISNewSwitch(dev, name, states, names, n);
1255 }
1256 
1257 bool LX200_10MICRON::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
1258 {
1259  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
1260  {
1261  if (strcmp(name, NEW_MODEL_NAME) == 0)
1262  {
1263  IUUpdateText(&NewModelNameTP, texts, names, n);
1265  IDSetText(&NewModelNameTP, nullptr);
1266  LOGF_INFO("Model saved with name %s", NewModelNameT[0].text);
1267  return true;
1268  }
1269  if (strcmp(name, "SAT_TLE_TEXT") == 0)
1270  {
1271 
1272  IUUpdateText(&TLEtoTrackTP, texts, names, n);
1273  if (0 == SetTLEtoFollow(TLEtoTrackT[0].text))
1274  {
1275  TLEtoTrackTP.s = IPS_OK;
1277  IDSetText(&TLEtoTrackTP, nullptr);
1278  IDSetNumber(&TLEfromDatabaseNP, nullptr);
1279  LOGF_INFO("Selected TLE %s", TLEtoTrackT[0].text);
1280  return true;
1281  }
1282  else
1283  {
1286  IDSetText(&TLEtoTrackTP, nullptr);
1287  IDSetNumber(&TLEfromDatabaseNP, nullptr);
1288  LOG_ERROR("TLE was not correctly uploaded");
1289  return false;
1290  }
1291  }
1292  if (strcmp(name, "SAT_PASS_WINDOW") == 0)
1293  {
1294  IUUpdateText(&SatPassWindowTP, texts, names, n);
1296  {
1298  IDSetText(&SatPassWindowTP, nullptr);
1299  LOG_INFO("Trajectory set");
1300  return true;
1301  }
1302  else
1303  {
1305  IDSetText(&SatPassWindowTP, nullptr);
1306  LOG_ERROR("Trajectory could not be calculated");
1307  return false;
1308  }
1309  }
1310  }
1311  return LX200Generic::ISNewText(dev, name, texts, names, n);
1312 }
1313 
1314 // this should move to some generic library
1315 int LX200_10MICRON::monthToNumber(const char *monthName)
1316 {
1317  struct entry
1318  {
1319  const char *name;
1320  int id;
1321  };
1322  entry month_table[] = { { "Jan", 1 }, { "Feb", 2 }, { "Mar", 3 }, { "Apr", 4 }, { "May", 5 },
1323  { "Jun", 6 }, { "Jul", 7 }, { "Aug", 8 }, { "Sep", 9 }, { "Oct", 10 },
1324  { "Nov", 11 }, { "Dec", 12 }, { nullptr, 0 }
1325  };
1326  entry *p = month_table;
1327  while (p->name != nullptr)
1328  {
1329  if (strcasecmp(p->name, monthName) == 0)
1330  return p->id;
1331  ++p;
1332  }
1333  return 0;
1334 }
1335 
1337 {
1338  int error_type;
1339  int nbytes_write = 0;
1340 
1341  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s>", data);
1342  if ((error_type = tty_write_string(fd, data, &nbytes_write)) != TTY_OK)
1343  {
1344  return error_type;
1345  }
1346  tcflush(fd, TCIFLUSH);
1347  return 0;
1348 }
1349 int LX200_10MICRON::setStandardProcedureAndExpect(int fd, const char *data, const char *expect)
1350 {
1351  char bool_return[2];
1352  int error_type;
1353  int nbytes_write = 0, nbytes_read = 0;
1354 
1355  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s>", data);
1356 
1357  tcflush(fd, TCIFLUSH);
1358 
1359  if ((error_type = tty_write_string(fd, data, &nbytes_write)) != TTY_OK)
1360  return error_type;
1361 
1362  error_type = tty_read(fd, bool_return, 1, LX200_TIMEOUT, &nbytes_read);
1363 
1364  tcflush(fd, TCIFLUSH);
1365 
1366  if (nbytes_read < 1)
1367  return error_type;
1368 
1369  if (bool_return[0] != expect[0])
1370  {
1371  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s> failed.", data);
1372  return -1;
1373  }
1374 
1375  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s> successful.", data);
1376 
1377  return 0;
1378 }
1379 
1380 int LX200_10MICRON::setStandardProcedureAndReturnResponse(int fd, const char *data, char *response, int max_response_length)
1381 {
1382  int error_type;
1383  int nbytes_write = 0, nbytes_read = 0;
1384 
1385  DEBUGFDEVICE(getDefaultName(), DBG_SCOPE, "CMD <%s>", data);
1386 
1387  tcflush(fd, TCIFLUSH);
1388 
1389  if ((error_type = tty_write_string(fd, data, &nbytes_write)) != TTY_OK)
1390  return error_type;
1391 
1392  error_type = tty_read(fd, response, max_response_length, LX200_TIMEOUT, &nbytes_read);
1393 
1394  tcflush(fd, TCIFLUSH);
1395 
1396  if (nbytes_read < 1)
1397  return error_type;
1398 
1399  return 0;
1400 }
LX200_10MICRON::ProductTP
ITextVectorProperty ProductTP
Definition: lx200_10micron.h:142
LX200Generic
Definition: lx200generic.h:25
LX200_10MICRON::GSTAT_TRACKING
@ GSTAT_TRACKING
Definition: lx200_10micron.h:48
LX200_10MICRON::MALPRO_MDEC
@ MALPRO_MDEC
Definition: lx200_10micron.h:78
LX200_10MICRON::CalculateSatTrajectory
bool CalculateSatTrajectory(std::string start_pass_isodatetime, std::string end_pass_isodatetime)
Definition: lx200_10micron.cpp:770
INDI::Telescope::TELESCOPE_CAN_PARK
@ TELESCOPE_CAN_PARK
Definition: inditelescope.h:161
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::Telescope::SCOPE_IDLE
@ SCOPE_IDLE
Definition: inditelescope.h:75
LX200_10MICRON::GSTAT_UNPARKING
@ GSTAT_UNPARKING
Definition: lx200_10micron.h:51
LX200_10MICRON::NewAlpN
INumber NewAlpN[ALP_COUNT]
Definition: lx200_10micron.h:166
LX200Telescope::mountSim
void mountSim()
Definition: lx200telescope.cpp:1061
INDI::Telescope::TELESCOPE_HAS_TRACK_RATE
@ TELESCOPE_HAS_TRACK_RATE
Definition: inditelescope.h:169
IUGetConfigSwitch
int IUGetConfigSwitch(const char *dev, const char *property, const char *member, ISState *value)
IUGetConfigSwitch Opens configuration file and reads single switch property.
Definition: indidriver.c:1212
LX200_10MICRON::GSTAT_NEED_USEROK
@ GSTAT_NEED_USEROK
Definition: lx200_10micron.h:59
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::SAT_PASS_WINDOW_START
@ SAT_PASS_WINDOW_START
Index for start of the window.
Definition: inditelescope.h:810
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
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
LX200_10MICRON::RefractionModelTemperatureNP
INumberVectorProperty RefractionModelTemperatureNP
Definition: lx200_10micron.h:146
LX200_10MICRON::PRODUCT_COUNT
@ PRODUCT_COUNT
Definition: lx200_10micron.h:42
LX200_10MICRON::monthToNumber
int monthToNumber(const char *monthName)
Definition: lx200_10micron.cpp:1315
fd
int fd
Definition: indiserver.c:117
INDI::Telescope::PIER_WEST
@ PIER_WEST
Definition: inditelescope.h:124
LX200Telescope::DBG_SCOPE
uint8_t DBG_SCOPE
Definition: lx200telescope.h:174
INDI::Telescope::SCOPE_SLEWING
@ SCOPE_SLEWING
Definition: inditelescope.h:76
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
INDI::Telescope::SAT_TRACK
@ SAT_TRACK
Track signal.
Definition: inditelescope.h:826
LX200_10MICRON::UNATTENDED_FLIP_ENABLED
@ UNATTENDED_FLIP_ENABLED
Definition: lx200_10micron.h:32
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
LX200_10MICRON::ALIGN_START
@ ALIGN_START
Definition: lx200_10micron.h:94
INDI::Telescope::SCOPE_PARKING
@ SCOPE_PARKING
Definition: inditelescope.h:78
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
min
double min(void)
LX200_10MICRON::AlignmentStateSP
ISwitchVectorProperty AlignmentStateSP
Definition: lx200_10micron.h:159
LX200_10MICRON::saveConfigItems
bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: lx200_10micron.cpp:189
INDI::Telescope::setPierSide
void setPierSide(TelescopePierSide side)
Definition: inditelescope.cpp:2605
LX200_10MICRON::GSTAT_FOLLOWING_SATELLITE
@ GSTAT_FOLLOWING_SATELLITE
Definition: lx200_10micron.h:58
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
LX200_10MICRON::AlignmentPointsNP
INumberVectorProperty AlignmentPointsNP
Definition: lx200_10micron.h:156
LX200_10MICRON::UNATTENDED_FLIP_COUNT
@ UNATTENDED_FLIP_COUNT
Definition: lx200_10micron.h:33
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
LX200_10MICRON::ALP_SIDTIME
@ ALP_SIDTIME
Definition: lx200_10micron.h:69
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
f_scansexa
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double.
Definition: indicom.c:201
LX200_10MICRON::PRODUCT_FIRMWARE_VERSION
@ PRODUCT_FIRMWARE_VERSION
Definition: lx200_10micron.h:40
INDI::Telescope::NewRaDec
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
Definition: inditelescope.cpp:693
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
LX200Telescope::sendTimeOnStartup
bool sendTimeOnStartup
Definition: lx200telescope.h:173
LX200_10MICRON::Handshake
bool Handshake() override
perform handshake with device to check communication
Definition: lx200_10micron.cpp:91
LX200_10MICRON::ALIGN_COUNT
@ ALIGN_COUNT
Definition: lx200_10micron.h:97
LX200_10MICRON::setStandardProcedureAndReturnResponse
int setStandardProcedureAndReturnResponse(int fd, const char *data, char *response, int max_response_length)
Definition: lx200_10micron.cpp:1380
NEW_ALIGNMENT_POINTS
#define NEW_ALIGNMENT_POINTS
Definition: lx200_10micron.cpp:53
LX200_10MICRON::GSTAT_MOTORS_TOO_COLD
@ GSTAT_MOTORS_TOO_COLD
Definition: lx200_10micron.h:56
LX200_10MICRON::AlignmentPointsN
INumber AlignmentPointsN[1]
Definition: lx200_10micron.h:155
LX200_10MICRON::NewModelNameT
IText NewModelNameT[1]
Definition: lx200_10micron.h:172
LX200_10MICRON::MALP_COUNT
@ MALP_COUNT
Definition: lx200_10micron.h:88
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
SATELLITE_TAB
const char * SATELLITE_TAB
SATELLITE_TAB.
Definition: defaultdevice.cpp:44
MINIMAL_NEW_ALIGNMENT_POINT
#define MINIMAL_NEW_ALIGNMENT_POINT
Definition: lx200_10micron.cpp:51
INDI::Telescope::TELESCOPE_HAS_TRACK_MODE
@ TELESCOPE_HAS_TRACK_MODE
Definition: inditelescope.h:167
INDI::Telescope::TLEtoTrackT
IText TLEtoTrackT[1]
Definition: inditelescope.h:803
LX200_10MICRON::ALP_MSIDE
@ ALP_MSIDE
Definition: lx200_10micron.h:68
LX200_10MICRON::GSTAT_TRACKING_OUTSIDE_LIMITS
@ GSTAT_TRACKING_OUTSIDE_LIMITS
Definition: lx200_10micron.h:57
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
lx200driver.h
LX200_10MICRON::MALPRO_COUNT
@ MALPRO_COUNT
Definition: lx200_10micron.h:81
LX200_10MICRON::ALIGN_END
@ ALIGN_END
Definition: lx200_10micron.h:95
LX200_10MICRON::TrackSat
bool TrackSat()
Definition: lx200_10micron.cpp:833
tty_read_section
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:557
LX200_10MICRON::UnPark
bool UnPark() override
Unpark the telescope if already parked.
Definition: lx200_10micron.cpp:550
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
LX200_10MICRON::NewAlignmentPointsNP
INumberVectorProperty NewAlignmentPointsNP
Definition: lx200_10micron.h:170
ALIGNMENT_POINTS
#define ALIGNMENT_POINTS
Definition: lx200_10micron.cpp:48
LX200_10MICRON::GSTAT_NOT_TRACKING_AND_NOT_MOVING
@ GSTAT_NOT_TRACKING_AND_NOT_MOVING
Definition: lx200_10micron.h:55
LX200_10MICRON::initProperties
bool initProperties() override
Called to initialize basic properties required all the time.
Definition: lx200_10micron.cpp:119
LX200_10MICRON::setStandardProcedureWithoutRead
int setStandardProcedureWithoutRead(int fd, const char *data)
Definition: lx200_10micron.cpp:1336
LX200_10MICRON::ALP_PDEC
@ ALP_PDEC
Definition: lx200_10micron.h:71
lx200_10micron.h
IUUpdateText
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:259
LX200_10MICRON::SyncConfigBehaviour
bool SyncConfigBehaviour(bool cmcfg)
Definition: lx200_10micron.cpp:630
LX200_10MICRON::MALP_PRA
@ MALP_PRA
Definition: lx200_10micron.h:86
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
LX200Telescope::sendScopeLocation
virtual bool sendScopeLocation()
Definition: lx200telescope.cpp:1377
LX200_10MICRON::ALP_MRA
@ ALP_MRA
Definition: lx200_10micron.h:66
max
double max(void)
INDI::Telescope::TrackState
TelescopeStatus TrackState
Definition: inditelescope.h:693
LX200_10MICRON::MiniNewAlpRON
INumber MiniNewAlpRON[MALPRO_COUNT]
Definition: lx200_10micron.h:161
LX200Telescope::sendScopeTime
virtual bool sendScopeTime()
Definition: lx200telescope.cpp:1310
INDI::Telescope::isParked
bool isParked()
isParked is mount currently parked?
Definition: inditelescope.cpp:1945
LX200_10MICRON::ISNewNumber
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: lx200_10micron.cpp:975
LX200_10MICRON::TLEfromDatabaseN
INumber TLEfromDatabaseN[1]
Definition: lx200_10micron.h:175
INDI::Telescope::SatPassWindowT
IText SatPassWindowT[SAT_PASS_WINDOW_COUNT]
Definition: inditelescope.h:819
LX200_10MICRON::GSTAT_PARKED
@ GSTAT_PARKED
Definition: lx200_10micron.h:53
LX200_10MICRON::ModelCountNP
INumberVectorProperty ModelCountNP
Definition: lx200_10micron.h:153
LX200_10MICRON::ALP_COUNT
@ ALP_COUNT
Definition: lx200_10micron.h:72
MINIMAL_NEW_ALIGNMENT_POINT_RO
#define MINIMAL_NEW_ALIGNMENT_POINT_RO
Definition: lx200_10micron.cpp:50
tty_read
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:473
INDI::Telescope::TELESCOPE_HAS_TIME
@ TELESCOPE_HAS_TIME
Definition: inditelescope.h:163
LX200_10MICRON::ISNewText
bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: lx200_10micron.cpp:1257
LX200_10MICRON::ALP_PRA
@ ALP_PRA
Definition: lx200_10micron.h:70
LX200_10MICRON::ProductT
IText ProductT[4]
Definition: lx200_10micron.h:141
INDI::Telescope::TELESCOPE_HAS_LOCATION
@ TELESCOPE_HAS_LOCATION
Definition: inditelescope.h:164
LX200_10MICRON::setUnattendedFlipSetting
bool setUnattendedFlipSetting(bool setting)
Definition: lx200_10micron.cpp:589
LX200_10MICRON::SetRefractionModelPressure
virtual int SetRefractionModelPressure(double pressure)
Definition: lx200_10micron.cpp:897
LX200_10MICRON::GSTAT_PARKING
@ GSTAT_PARKING
Definition: lx200_10micron.h:50
LX200_10MICRON::ALIGN_IDLE
@ ALIGN_IDLE
Definition: lx200_10micron.h:93
LX200_TIMEOUT
#define LX200_TIMEOUT
Definition: lx200_10micron.cpp:42
LX200_10MICRON::MiniNewAlpRONP
INumberVectorProperty MiniNewAlpRONP
Definition: lx200_10micron.h:162
LX200_10MICRON::LX200_10MICRON
LX200_10MICRON()
Definition: lx200_10micron.cpp:62
LX200Telescope::sendLocationOnStartup
bool sendLocationOnStartup
Definition: lx200telescope.h:173
LX200_10MICRON::ISNewSwitch
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: lx200_10micron.cpp:1098
_ISwitchVectorProperty::nsp
int nsp
Definition: indiapi.h:386
LX200_10MICRON::RefractionModelTemperatureN
INumber RefractionModelTemperatureN[1]
Definition: lx200_10micron.h:145
LX200_10MICRON::MALPRO_MRA
@ MALPRO_MRA
Definition: lx200_10micron.h:77
LX200_10MICRON::GSTAT_STOPPED
@ GSTAT_STOPPED
Definition: lx200_10micron.h:49
NEW_ALIGNMENT_POINT
#define NEW_ALIGNMENT_POINT
Definition: lx200_10micron.cpp:52
INDI::Telescope::TLEtoTrackTP
ITextVectorProperty TLEtoTrackTP
Text Vector property defining the orbital elements of an artificial satellite (TLE)....
Definition: inditelescope.h:802
LX200_10MICRON::flip
bool flip()
Definition: lx200_10micron.cpp:614
LX200_10MICRON::AlignmentStateS
ISwitch AlignmentStateS[ALIGN_COUNT]
Definition: lx200_10micron.h:158
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::Telescope::SetTelescopeCapability
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount=0)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
Definition: inditelescope.cpp:1818
LX200_10MICRON::GSTAT_UNSET
@ GSTAT_UNSET
Definition: lx200_10micron.h:47
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
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
LX200Telescope::initProperties
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition: lx200telescope.cpp:64
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
ALIGNMENT_TAB
#define ALIGNMENT_TAB
Definition: lx200_10micron.cpp:41
INDI::Telescope::TELESCOPE_CAN_ABORT
@ TELESCOPE_CAN_ABORT
Definition: inditelescope.h:162
LX200_10MICRON::UnattendedFlip
int UnattendedFlip
Definition: lx200_10micron.h:137
LX200_10MICRON::setStandardProcedureAndExpect
int setStandardProcedureAndExpect(int fd, const char *data, const char *expect)
Definition: lx200_10micron.cpp:1349
LX200Telescope::LX200_HAS_TRACKING_FREQ
@ LX200_HAS_TRACKING_FREQ
Definition: lx200telescope.h:45
setStandardProcedure
int setStandardProcedure(int fd, const char *writeData)
Definition: lx200driver.cpp:821
extractISOTime
int extractISOTime(const char *timestr, struct ln_date *iso_date)
Extract ISO 8601 time and store it in a tm struct.
PRODUCT_TAB
#define PRODUCT_TAB
Definition: lx200_10micron.cpp:40
LX200Telescope::LX200_HAS_PULSE_GUIDING
@ LX200_HAS_PULSE_GUIDING
Definition: lx200telescope.h:48
INDI::Telescope::TELESCOPE_HAS_PIER_SIDE
@ TELESCOPE_HAS_PIER_SIDE
Definition: inditelescope.h:165
LX200_10MICRON::SetTLEtoFollow
bool SetTLEtoFollow(const char *tle)
Definition: lx200_10micron.cpp:665
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::Telescope::TELESCOPE_CAN_CONTROL_TRACK
@ TELESCOPE_CAN_CONTROL_TRACK
Definition: inditelescope.h:168
LX200_10MICRON::getUnattendedFlipSetting
bool getUnattendedFlipSetting()
Definition: lx200_10micron.cpp:566
INDI::Telescope::SAT_HALT
@ SAT_HALT
Halt signal (abort)
Definition: inditelescope.h:827
LX200_10MICRON::PRODUCT_FIRMWARE_DATE
@ PRODUCT_FIRMWARE_DATE
Definition: lx200_10micron.h:41
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
LX200_10MICRON::updateProperties
bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: lx200_10micron.cpp:197
getTrackFreq
int getTrackFreq(int fd, double *value)
Definition: lx200driver.cpp:703
INDI::Telescope::SCOPE_TRACKING
@ SCOPE_TRACKING
Definition: inditelescope.h:77
getCommandInt
int getCommandInt(int fd, int *value, const char *cmd)
Definition: lx200driver.cpp:278
LX200_10MICRON::ALIGN_DELETE_CURRENT
@ ALIGN_DELETE_CURRENT
Definition: lx200_10micron.h:96
LX200Telescope::timeFormat
int timeFormat
Definition: lx200telescope.h:169
LX200_10MICRON::ModelCountN
INumber ModelCountN[1]
Definition: lx200_10micron.h:152
LX200_10MICRON::setLocalDate
bool setLocalDate(uint8_t days, uint8_t months, uint16_t years) override
Definition: lx200_10micron.cpp:651
LX200_10MICRON::getBasicData
void getBasicData() override
Definition: lx200_10micron.cpp:264
INDI::Telescope::SCOPE_PARKED
@ SCOPE_PARKED
Definition: inditelescope.h:79
REFRACTION_MODEL_PRESSURE
#define REFRACTION_MODEL_PRESSURE
Definition: lx200_10micron.cpp:46
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
REFRACTION_MODEL_TEMPERATURE
#define REFRACTION_MODEL_TEMPERATURE
Definition: lx200_10micron.cpp:45
LX200_10MICRON::GSTAT_ERROR
@ GSTAT_ERROR
Definition: lx200_10micron.h:61
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
LX200_10MICRON::Park
bool Park() override
Park the telescope to its home position.
Definition: lx200_10micron.cpp:534
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
UNATTENDED_FLIP
#define UNATTENDED_FLIP
Definition: lx200_10micron.cpp:60
LX200_10MICRON::ALP_MDEC
@ ALP_MDEC
Definition: lx200_10micron.h:67
INDI::Telescope::TELESCOPE_CAN_GOTO
@ TELESCOPE_CAN_GOTO
Definition: inditelescope.h:159
LX200Telescope::getAlignment
void getAlignment()
Definition: lx200telescope.cpp:1231
LX200Telescope::setLX200Capability
void setLX200Capability(uint32_t cap)
Definition: lx200telescope.h:56
LX200_10MICRON::NewAlpNP
INumberVectorProperty NewAlpNP
Definition: lx200_10micron.h:167
setCommandInt
int setCommandInt(int fd, int data, const char *cmd)
Definition: lx200driver.cpp:855
INDI::Telescope::TELESCOPE_CAN_SYNC
@ TELESCOPE_CAN_SYNC
Definition: inditelescope.h:160
name
const char * name
Definition: indiserver.c:116
LX200_10MICRON::RefractionModelPressureNP
INumberVectorProperty RefractionModelPressureNP
Definition: lx200_10micron.h:150
MODEL_COUNT
#define MODEL_COUNT
Definition: lx200_10micron.cpp:47
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
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
ALIGNMENT_STATE
#define ALIGNMENT_STATE
Definition: lx200_10micron.cpp:49
LX200_10MICRON::MiniNewAlpNP
INumberVectorProperty MiniNewAlpNP
Definition: lx200_10micron.h:164
DEBUGFDEVICE
#define DEBUGFDEVICE(device, priority, msg,...)
Definition: indilogger.h:61
NEW_MODEL_NAME
#define NEW_MODEL_NAME
Definition: lx200_10micron.cpp:54
LX200_10MICRON::UnattendedFlipSP
ISwitchVectorProperty UnattendedFlipSP
Definition: lx200_10micron.h:139
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
LX200_10MICRON::MiniNewAlpN
INumber MiniNewAlpN[MALP_COUNT]
Definition: lx200_10micron.h:163
LX200_10MICRON::GSTAT_SLEWING_TO_HOME
@ GSTAT_SLEWING_TO_HOME
Definition: lx200_10micron.h:52
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
LX200_10MICRON::AddSyncPointHere
int AddSyncPointHere(double PRa, double PDec)
Definition: lx200_10micron.cpp:969
fs_sexa
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string.
Definition: indicom.c:137
LX200_10MICRON::NewAlignmentPointsN
INumber NewAlignmentPointsN[1]
Definition: lx200_10micron.h:169
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
LX200_10MICRON::NewModelNameTP
ITextVectorProperty NewModelNameTP
Definition: lx200_10micron.h:173
LX200_10MICRON::PRODUCT_NAME
@ PRODUCT_NAME
Definition: lx200_10micron.h:38
LX200_10MICRON::GSTAT_UNKNOWN_STATUS
@ GSTAT_UNKNOWN_STATUS
Definition: lx200_10micron.h:60
LX200Telescope::TrackFreqNP
INumberVectorProperty TrackFreqNP
Definition: lx200telescope.h:186
getCommandString
int getCommandString(int fd, char *data, const char *cmd)
Definition: lx200driver.cpp:321
checkLX200EquatorialFormat
int checkLX200EquatorialFormat(int fd)
Definition: lx200driver.cpp:1698
LX200_10MICRON::RefractionModelPressureN
INumber RefractionModelPressureN[1]
Definition: lx200_10micron.h:149
ISState
ISState
Switch state.
Definition: indiapi.h:148
LX200_10MICRON::PRODUCT_CONTROL_BOX
@ PRODUCT_CONTROL_BOX
Definition: lx200_10micron.h:39
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
LX200_10MICRON::AddSyncPoint
int AddSyncPoint(double MRa, double MDec, double MSide, double PRa, double PDec, double SidTime)
Definition: lx200_10micron.cpp:911
INDI::Telescope::SAT_PASS_WINDOW_END
@ SAT_PASS_WINDOW_END
Index for end of the window.
Definition: inditelescope.h:811
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
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
INDI::Telescope::TrackSatSP
ISwitchVectorProperty TrackSatSP
Switch Vector property defining the state of the satellite tracking of the mount. Example implementat...
Definition: inditelescope.h:834
tty_write_string
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:465
TTY_OK
@ TTY_OK
Definition: indicom.h:94
LX200_24
@ LX200_24
Definition: lx200driver.h:64
PRODUCT_INFO
#define PRODUCT_INFO
Definition: lx200_10micron.cpp:55
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
LX200_10MICRON::TLEfromDatabaseNP
INumberVectorProperty TLEfromDatabaseNP
Definition: lx200_10micron.h:176
LX200_10MICRON::UnattendedFlipS
ISwitch UnattendedFlipS[UNATTENDED_FLIP_COUNT]
Definition: lx200_10micron.h:138
LX200_10MICRON::SetRefractionModelTemperature
virtual int SetRefractionModelTemperature(double temperature)
Definition: lx200_10micron.cpp:884
LX200Telescope::updateProperties
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
Definition: lx200telescope.cpp:199
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::TrackFreqN
INumber TrackFreqN[1]
Definition: lx200telescope.h:187
INDI::Telescope::PIER_EAST
@ PIER_EAST
Definition: inditelescope.h:125
LX200_10MICRON::getDefaultName
const char * getDefaultName() override
Definition: lx200_10micron.cpp:85
LX200_10MICRON::GSTAT_SLEWING_OR_STOPPING
@ GSTAT_SLEWING_OR_STOPPING
Definition: lx200_10micron.h:54
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
LX200_10MICRON::SetTLEfromDatabase
bool SetTLEfromDatabase(int tleN)
Definition: lx200_10micron.cpp:738
INDI::Telescope::TELESCOPE_CAN_TRACK_SATELLITE
@ TELESCOPE_CAN_TRACK_SATELLITE
Definition: inditelescope.h:171
LX200_10MICRON::MALPRO_MSIDE
@ MALPRO_MSIDE
Definition: lx200_10micron.h:79
LX200_10MICRON::ReadScopeStatus
bool ReadScopeStatus() override
Read telescope status.
Definition: lx200_10micron.cpp:386
INDI::Telescope::SatPassWindowTP
ITextVectorProperty SatPassWindowTP
Text Vector property defining the start and end of a satellite pass (window contains pass)....
Definition: inditelescope.h:818
LX200_10MICRON::MALP_PDEC
@ MALP_PDEC
Definition: lx200_10micron.h:87
LX200_10MICRON::MALPRO_SIDTIME
@ MALPRO_SIDTIME
Definition: lx200_10micron.h:80
LX200_10MICRON::UNATTENDED_FLIP_DISABLED
@ UNATTENDED_FLIP_DISABLED
Definition: lx200_10micron.h:31
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151