Instrument Neutral Distributed Interface INDI  2.0.2
indicom.c
Go to the documentation of this file.
1 /*
2  INDI LIB
3  Common routines used by all drivers
4  Copyright (C) 2003 by Jason Harris (jharris@30doradus.org)
5  Elwood C. Downey
6 
7  This is the C version of the astronomical library in KStars
8  modified by Jasem Mutlaq (mutlaqja@ikarustech.com)
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Lesser General Public
12  License as published by the Free Software Foundation; either
13  version 2.1 of the License, or (at your option) any later version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; 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; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 
24 */
25 
26 #define _GNU_SOURCE 1
27 
28 #include "indicom.h"
29 
30 #include "indidevapi.h"
31 #include "locale_compat.h"
32 #include "base64.h"
33 
34 #include "config.h"
35 
36 #if defined(HAVE_LIBNOVA)
37 #include <libnova/julian_day.h>
38 #include <libnova/sidereal_time.h>
39 #include <libnova/ln_types.h>
40 #include <libnova/transform.h>
41 #endif // HAVE_LIBNOVA
42 
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <math.h>
46 #include <stdarg.h>
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <time.h>
52 
53 #ifdef __linux__
54 #include <sys/ioctl.h>
55 #endif
56 
57 #ifdef __APPLE__
58 #include <sys/param.h>
59 #include <mach/clock.h>
60 #include <mach/mach.h>
61 #endif
62 
63 #ifdef __FreeBSD__
64 #include <sys/param.h>
65 #endif
66 
67 #if defined(BSD) && !defined(__GNU__)
68 #ifdef __APPLE__
69 #include <IOKit/serial/ioss.h>
70 #endif
71 #include <sys/ioctl.h>
72 #endif
73 
74 #ifdef __GNU__
75 #include <sys/ioctl.h>
76 #endif
77 
78 #ifdef _WIN32
79 #undef CX
80 #undef CY
81 #endif
82 
83 #ifndef _WIN32
84 #include <unistd.h>
85 #include <termios.h>
86 #include <sys/param.h>
87 #define PARITY_NONE 0
88 #define PARITY_EVEN 1
89 #define PARITY_ODD 2
90 #endif
91 
92 #include "userio.h"
93 #include "indiuserio.h"
94 
95 #if defined(_MSC_VER)
96 #define snprintf _snprintf
97 #pragma warning(push)
99 #pragma warning(disable : 4996)
100 #endif
101 
102 #define MAXRBUF 2048
103 
104 static int tty_debug = 0;
105 static int tty_gemini_udp_format = 0;
106 static int tty_generic_udp_format = 0;
107 static int tty_sequence_number = 1;
108 static int tty_clear_trailing_lf = 0;
109 
110 #if defined(HAVE_LIBNOVA)
111 int extractISOTime(const char *timestr, struct ln_date *iso_date)
112 {
113  struct tm utm;
114 
115  if (strptime(timestr, "%Y/%m/%dT%H:%M:%S", &utm))
116  {
117  ln_get_date_from_tm(&utm, iso_date);
118  return (0);
119  }
120 
121  if (strptime(timestr, "%Y-%m-%dT%H:%M:%S", &utm))
122  {
123  ln_get_date_from_tm(&utm, iso_date);
124  return (0);
125  }
126 
127  return (-1);
128 }
129 #endif
130 
131 /* sprint the variable a in sexagesimal format into out[].
132  * w is the number of spaces for the whole part.
133  * fracbase is the number of pieces a whole is to broken into; valid options:
134  * 360000: <w>:mm:ss.ss
135  * 36000: <w>:mm:ss.s
136  * 3600: <w>:mm:ss
137  * 600: <w>:mm.m
138  * 60: <w>:mm
139  * return number of characters written to out, not counting final '\0'.
140  */
141 int fs_sexa(char *out, double a, int w, int fracbase)
142 {
143  char *out0 = out;
144  unsigned long n;
145  int d;
146  int f;
147  int m;
148  int s;
149  int isneg;
150 
151  /* save whether it's negative but do all the rest with a positive */
152  isneg = (a < 0);
153  if (isneg)
154  a = -a;
155 
156  /* convert to an integral number of whole portions */
157  n = (unsigned long)(a * fracbase + 0.5);
158  d = n / fracbase;
159  f = n % fracbase;
160 
161  /* form the whole part; "negative 0" is a special case */
162  if (isneg && d == 0)
163  out += snprintf(out, MAXINDIFORMAT, "%*s-0", w - 2, "");
164  else
165  out += snprintf(out, MAXINDIFORMAT, "%*d", w, isneg ? -d : d);
166 
167  /* do the rest */
168  switch (fracbase)
169  {
170  case 60: /* dd:mm */
171  m = f / (fracbase / 60);
172  out += snprintf(out, MAXINDIFORMAT, ":%02d", m);
173  break;
174  case 600: /* dd:mm.m */
175  out += snprintf(out, MAXINDIFORMAT, ":%02d.%1d", f / 10, f % 10);
176  break;
177  case 3600: /* dd:mm:ss */
178  m = f / (fracbase / 60);
179  s = f % (fracbase / 60);
180  out += snprintf(out, MAXINDIFORMAT, ":%02d:%02d", m, s);
181  break;
182  case 36000: /* dd:mm:ss.s*/
183  m = f / (fracbase / 60);
184  s = f % (fracbase / 60);
185  out += snprintf(out, MAXINDIFORMAT, ":%02d:%02d.%1d", m, s / 10, s % 10);
186  break;
187  case 360000: /* dd:mm:ss.ss */
188  m = f / (fracbase / 60);
189  s = f % (fracbase / 60);
190  out += snprintf(out, MAXINDIFORMAT, ":%02d:%02d.%02d", m, s / 100, s % 100);
191  break;
192  default:
193  printf("fs_sexa: unknown fracbase: %d\n", fracbase);
194  return -1;
195  }
196 
197  return (int)(out - out0);
198 }
199 
200 /* convert sexagesimal string str AxBxC to double.
201  * x can be anything non-numeric. Any missing A, B or C will be assumed 0.
202  * optional - and + can be anywhere.
203  * return 0 if ok, -1 if can't find a thing.
204  */
205 int f_scansexa(const char *str0, /* input string */
206  double *dp) /* cracked value, if return 0 */
207 {
208  locale_char_t *orig = indi_locale_C_numeric_push();
209 
210  double a = 0, b = 0, c = 0;
211  char str[128];
212  //char *neg;
213  uint8_t isNegative=0;
214  int r= 0;
215 
216  /* copy str0 so we can play with it */
217  strncpy(str, str0, sizeof(str) - 1);
218  str[sizeof(str) - 1] = '\0';
219 
220  /* remove any spaces */
221  char* i = str;
222  char* j = str;
223  while(*j != 0)
224  {
225  *i = *j++;
226  if(*i != ' ')
227  i++;
228  }
229  *i = 0;
230 
231  // This has problem process numbers in scientific notations e.g. 1e-06
232  /*neg = strchr(str, '-');
233  if (neg)
234  *neg = ' ';
235  */
236  if (str[0] == '-')
237  {
238  isNegative = 1;
239  str[0] = ' ';
240  }
241 
242  r = sscanf(str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c);
243 
244  indi_locale_C_numeric_pop(orig);
245 
246  if (r < 1)
247  return (-1);
248  *dp = a + b / 60 + c / 3600;
249  if (isNegative)
250  *dp *= -1;
251  return (0);
252 }
253 
254 void getSexComponents(double value, int *d, int *m, int *s)
255 {
256  *d = (int32_t)fabs(value);
257  *m = (int32_t)((fabs(value) - *d) * 60.0);
258  *s = (int32_t)rint(((fabs(value) - *d) * 60.0 - *m) * 60.0);
259 
260  // Special case if seconds are >= 59.5 so it will be rounded by rint above
261  // to 60
262  if (*s == 60)
263  {
264  *s = 0;
265  *m += 1;
266  }
267  if (*m == 60)
268  {
269  *m = 0;
270  *d += 1;
271  }
272 
273  if (value < 0)
274  *d *= -1;
275 }
276 
277 void getSexComponentsIID(double value, int *d, int *m, double *s)
278 {
279  *d = (int32_t)fabs(value);
280  *m = (int32_t)((fabs(value) - *d) * 60.0);
281  *s = (double)(((fabs(value) - *d) * 60.0 - *m) * 60.0);
282 
283  if (value < 0)
284  *d *= -1;
285 }
286 
287 /* fill buf with properly formatted INumber string. return length */
288 int numberFormat(char *buf, const char *format, double value)
289 {
290  int w, f, s;
291  char m;
292 
293  if (sscanf(format, "%%%d.%d%c", &w, &f, &m) == 3 && m == 'm')
294  {
295  /* INDI sexi format */
296  switch (f)
297  {
298  case 9: s = 360000; break;
299  case 8: s = 36000; break;
300  case 6: s = 3600; break;
301  case 5: s = 600; break;
302  default: s = 60; break;
303  }
304  return (fs_sexa(buf, value, w - f, s));
305  }
306  else
307  {
308  /* normal printf format */
309  return (snprintf(buf, MAXINDIFORMAT, format, value));
310  }
311 }
312 
313 /* log message locally.
314  * this has nothing to do with XML or any Clients.
315  */
316 void IDLog(const char *fmt, ...)
317 {
318  va_list ap;
319  /* JM: Since all INDI's stderr are timestampped now, we don't need to time stamp ID Log */
320  /*fprintf (stderr, "%s ", indi_timestamp());*/
321  va_start(ap, fmt);
322  vfprintf(stderr, fmt, ap);
323  va_end(ap);
324 }
325 
326 double time_ns()
327 {
328  struct timespec ts;
329 #if defined(HAVE_TIMESPEC_GET)
330  timespec_get(&ts, TIME_UTC);
331 #elif defined(HAVE_CLOCK_GETTIME)
332  clock_gettime(CLOCK_REALTIME, &ts);
333 #elif defined(__APPLE__) // OS X does not have clock_gettime, use clock_get_time
334  clock_serv_t cclock;
335  mach_timespec_t mts;
336  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
337  clock_get_time(cclock, &mts);
338  mach_port_deallocate(mach_task_self(), cclock);
339  ts.tv_sec = mts.tv_sec;
340  ts.tv_nsec = mts.tv_nsec;
341 #else
342  #error "Unsupported platform"
343 #endif
344  return (double)ts.tv_sec+(double)(ts.tv_nsec%1000000000)/1000000000.0;
345 }
346 
347 /* return current system time in message format */
348 const char *indi_timestamp()
349 {
350  static char ts[32];
351  struct tm *tp;
352  time_t t;
353 
354  time(&t);
355  tp = gmtime(&t);
356  strftime(ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
357  return (ts);
358 }
359 
360 void tty_set_debug(int debug)
361 {
362  tty_debug = debug;
363 }
364 
365 void tty_set_gemini_udp_format(int enabled)
366 {
367  tty_gemini_udp_format = enabled;
368 }
369 
370 void tty_set_generic_udp_format(int enabled)
371 {
372  tty_generic_udp_format = enabled;
373 }
374 
375 void tty_clr_trailing_read_lf(int enabled)
376 {
377  tty_clear_trailing_lf = enabled;
378 }
379 
380 int tty_timeout(int fd, int timeout)
381 {
382  return tty_timeout_microseconds(fd, timeout, 0);
383 }
384 
385 int tty_timeout_microseconds(int fd, long timeout_seconds, long timeout_microseconds)
386 {
387  #if defined(_WIN32) || defined(ANDROID)
388  INDI_UNUSED(fd);
389  INDI_UNUSED(timeout_seconds);
390  INDI_UNUSED(timeout_microseconds);
391  return TTY_ERRNO;
392  #else
393 
394  if (fd == -1)
395  return TTY_ERRNO;
396 
397  struct timeval tv;
398  fd_set readout;
399  int retval;
400 
401  FD_ZERO(&readout);
402  FD_SET(fd, &readout);
403 
404  /* wait for 'timeout' seconds + microseconds */
405  tv.tv_sec = timeout_seconds;
406  tv.tv_usec = timeout_microseconds;
407 
408  /* Wait till we have a change in the fd status */
409  retval = select(fd + 1, &readout, NULL, NULL, &tv);
410 
411  /* Return 0 on successful fd change */
412  if (retval > 0)
413  return TTY_OK;
414  /* Return -1 due to an error */
415  else if (retval == -1)
416  return TTY_SELECT_ERROR;
417  /* Return -2 if time expires before anything interesting happens */
418  else
419  return TTY_TIME_OUT;
420 
421  #endif
422 }
423 
424 int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
425 {
426 #ifdef _WIN32
427  return TTY_ERRNO;
428 #else
429  int geminiBuffer[66]={0};
430  char *buffer = (char *)buf;
431 
432  if (tty_gemini_udp_format)
433  {
434  buffer = (char*)geminiBuffer;
435  geminiBuffer[0] = ++tty_sequence_number;
436  geminiBuffer[1] = 0;
437  memcpy((char *)&geminiBuffer[2], buf, nbytes);
438  // Add on the 8 bytes for the header and 1 byte for the null terminator
439  nbytes += 9;
440  }
441 
442  if (fd == -1)
443  return TTY_ERRNO;
444 
445  int bytes_w = 0;
446  *nbytes_written = 0;
447 
448  if (tty_debug)
449  {
450  int i = 0;
451  for (i = 0; i < nbytes; i++)
452  IDLog("%s: buffer[%d]=%#X (%c)\n", __FUNCTION__, i, (unsigned char)buf[i], buf[i]);
453  }
454 
455  while (nbytes > 0)
456  {
457  bytes_w = write(fd, buffer + (*nbytes_written), nbytes);
458 
459  if (bytes_w < 0)
460  return TTY_WRITE_ERROR;
461 
462  *nbytes_written += bytes_w;
463  nbytes -= bytes_w;
464  }
465 
466  if (tty_gemini_udp_format)
467  *nbytes_written -= 9;
468 
469  return TTY_OK;
470 
471 #endif
472 }
473 
474 int tty_write_string(int fd, const char *buf, int *nbytes_written)
475 {
476  int nbytes;
477  nbytes = (int)strlen(buf);
478 
479  return tty_write(fd, buf, nbytes, nbytes_written);
480 }
481 
482 int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
483 {
484  return tty_read_expanded(fd, buf, nbytes, timeout, 0, nbytes_read);
485 }
486 
487 int tty_read_expanded(int fd, char *buf, int nbytes, long timeout_seconds, long timeout_microseconds, int *nbytes_read)
488 {
489 #ifdef _WIN32
490  return TTY_ERRNO;
491 #else
492 
493  if (fd == -1)
494  return TTY_ERRNO;
495 
496  int numBytesToRead = nbytes;
497  int bytesRead = 0;
498  int err = 0;
499  *nbytes_read = 0;
500 
501  if (nbytes <= 0)
502  return TTY_PARAM_ERROR;
503 
504  if (tty_debug)
505  IDLog("%s: Request to read %d bytes with %ld s, %ld us timeout for fd %d\n", __FUNCTION__, nbytes, timeout_seconds, timeout_microseconds, fd);
506 
507  char geminiBuffer[257]={0};
508  char* buffer = buf;
509 
510  if (tty_gemini_udp_format)
511  {
512  numBytesToRead = nbytes + 8;
513  buffer = geminiBuffer;
514  }
515 
516  while (numBytesToRead > 0)
517  {
518  if ((err = tty_timeout_microseconds(fd, timeout_seconds, timeout_microseconds)))
519  return err;
520 
521  bytesRead = read(fd, buffer + (*nbytes_read), ((uint32_t)numBytesToRead));
522 
523  if (bytesRead < 0)
524  return TTY_READ_ERROR;
525 
526  if (tty_debug)
527  {
528  IDLog("%d bytes read and %d bytes remaining...\n", bytesRead, numBytesToRead - bytesRead);
529  int i = 0;
530  for (i = *nbytes_read; i < (*nbytes_read + bytesRead); i++)
531  IDLog("%s: buffer[%d]=%#X (%c)\n", __FUNCTION__, i, (unsigned char)buf[i], buf[i]);
532  }
533 
534  if (*nbytes_read == 0 && tty_clear_trailing_lf && *buffer == 0x0A)
535  {
536  if (tty_debug)
537  IDLog("%s: Cleared LF char left in buf\n", __FUNCTION__);
538 
539  memcpy(buffer, buffer+1,bytesRead);
540  --bytesRead;
541  }
542 
543  *nbytes_read += bytesRead;
544  numBytesToRead -= bytesRead;
545  }
546 
547 
548  if (tty_gemini_udp_format)
549  {
550  int *intSizedBuffer = (int *)geminiBuffer;
551  if (intSizedBuffer[0] != tty_sequence_number)
552  {
553  // Not the right reply just do the read again.
554  return tty_read_expanded(fd, buf, nbytes, timeout_seconds, timeout_microseconds, nbytes_read);
555  }
556 
557  *nbytes_read -= 8;
558  memcpy(buf, geminiBuffer+8, *nbytes_read);
559  }
560 
561  return TTY_OK;
562 
563 #endif
564 }
565 
566 int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
567 {
568  return tty_read_section_expanded(fd, buf, stop_char, (long) timeout, (long) 0, nbytes_read);
569 }
570 
571 int tty_read_section_expanded(int fd, char *buf, char stop_char, long timeout_seconds, long timeout_microseconds, int *nbytes_read)
572 {
573 #ifdef _WIN32
574  return TTY_ERRNO;
575 #else
576 
577  char readBuffer[257]={0};
578 
579  if (fd == -1)
580  return TTY_ERRNO;
581 
582  int bytesRead = 0;
583  int err = TTY_OK;
584  *nbytes_read = 0;
585 
586  uint8_t *read_char = 0;
587 
588  if (tty_debug)
589  IDLog("%s: Request to read until stop char '%#02X' with %ld s %ld us timeout for fd %d\n", __FUNCTION__, stop_char, timeout_seconds, timeout_microseconds, fd);
590 
591  if (tty_gemini_udp_format)
592  {
593  bytesRead = read(fd, readBuffer, 255);
594 
595  if (bytesRead < 0)
596  return TTY_READ_ERROR;
597 
598  int *intSizedBuffer = (int *)readBuffer;
599  if (intSizedBuffer[0] != tty_sequence_number)
600  {
601  // Not the right reply just do the read again.
602  return tty_read_section_expanded(fd, buf, stop_char, timeout_seconds, timeout_microseconds, nbytes_read);
603  }
604 
605  for (int index = 8; index < bytesRead; index++)
606  {
607  (*nbytes_read)++;
608 
609  if (*(readBuffer+index) == stop_char)
610  {
611  strncpy(buf, readBuffer+8, *nbytes_read);
612  return TTY_OK;
613  }
614  }
615  }
616  else if (tty_generic_udp_format)
617  {
618  bytesRead = read(fd, readBuffer, 255);
619  if (bytesRead < 0)
620  return TTY_READ_ERROR;
621  for (int index = 0; index < bytesRead; index++)
622  {
623  (*nbytes_read)++;
624 
625  if (*(readBuffer+index) == stop_char)
626  {
627  strncpy(buf, readBuffer, *nbytes_read);
628  return TTY_OK;
629  }
630  }
631  }
632  else
633  {
634  for (;;)
635  {
636  if ((err = tty_timeout_microseconds(fd, timeout_seconds, timeout_microseconds)))
637  return err;
638 
639  read_char = (uint8_t*)(buf + *nbytes_read);
640  bytesRead = read(fd, read_char, 1);
641 
642  if (bytesRead < 0)
643  return TTY_READ_ERROR;
644 
645  if (tty_debug)
646  IDLog("%s: buffer[%d]=%#X (%c)\n", __FUNCTION__, (*nbytes_read), *read_char, *read_char);
647 
648  if (!(tty_clear_trailing_lf && *read_char == 0X0A && *nbytes_read == 0))
649  (*nbytes_read)++;
650  else {
651  if (tty_debug)
652  IDLog("%s: Cleared LF char left in buf\n", __FUNCTION__);
653  }
654 
655  if (*read_char == stop_char) {
656  return TTY_OK;
657  }
658  }
659  }
660 
661  return TTY_TIME_OUT;
662 
663 #endif
664 }
665 
666 int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
667 {
668 #ifdef _WIN32
669  return TTY_ERRNO;
670 #else
671 
672  if (fd == -1)
673  return TTY_ERRNO;
674 
675  // For Gemini
676  if (tty_gemini_udp_format || tty_generic_udp_format)
677  return tty_read_section(fd, buf, stop_char, timeout, nbytes_read);
678 
679  int bytesRead = 0;
680  int err = TTY_OK;
681  *nbytes_read = 0;
682  uint8_t *read_char = 0;
683  memset(buf, 0, nsize);
684 
685  if (tty_debug)
686  IDLog("%s: Request to read until stop char '%#02X' with %d timeout for fd %d\n", __FUNCTION__, stop_char, timeout, fd);
687 
688  for (;;)
689  {
690  if ((err = tty_timeout(fd, timeout)))
691  return err;
692 
693  read_char = (uint8_t*)(buf + *nbytes_read);
694  bytesRead = read(fd, read_char, 1);
695 
696  if (bytesRead < 0)
697  return TTY_READ_ERROR;
698 
699  if (tty_debug)
700  IDLog("%s: buffer[%d]=%#X (%c)\n", __FUNCTION__, (*nbytes_read), *read_char, *read_char);
701 
702  if (!(tty_clear_trailing_lf && *read_char == 0X0A && *nbytes_read == 0))
703  (*nbytes_read)++;
704  else {
705  if (tty_debug)
706  IDLog("%s: Cleared LF char left in buf\n", __FUNCTION__);
707  }
708 
709  if (*read_char == stop_char)
710  return TTY_OK;
711  else if (*nbytes_read >= nsize)
712  return TTY_OVERFLOW;
713  }
714 
715 #endif
716 }
717 
718 #if defined(BSD) && !defined(__GNU__)
719 // BSD - OSX version
720 int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
721 {
722  int t_fd = -1;
723  int bps;
724  char msg[80];
725  int handshake;
726  struct termios tty_setting;
727 
728  // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
729  // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
730  // See open(2) ("man 2 open") for details.
731 
732  t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
733  if (t_fd == -1)
734  {
735  IDLog("Error opening serial port (%s) - %s(%d).\n", device, strerror(errno), errno);
736  goto error;
737  }
738 
739  // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
740  // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
741  // processes.
742  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
743 
744  if (ioctl(t_fd, TIOCEXCL) == -1)
745  {
746  IDLog("Error setting TIOCEXCL on %s - %s(%d).\n", device, strerror(errno), errno);
747  goto error;
748  }
749 
750  // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
751  // See fcntl(2) ("man 2 fcntl") for details.
752 
753  if (fcntl(t_fd, F_SETFL, 0) == -1)
754  {
755  IDLog("Error clearing O_NONBLOCK %s - %s(%d).\n", device, strerror(errno), errno);
756  goto error;
757  }
758 
759  // Get the current options and save them so we can restore the default settings later.
760  if (tcgetattr(t_fd, &tty_setting) == -1)
761  {
762  IDLog("Error getting tty attributes %s - %s(%d).\n", device, strerror(errno), errno);
763  goto error;
764  }
765 
766  // Set raw input (non-canonical) mode, with reads blocking until either a single character
767  // has been received or a one second timeout expires.
768  // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
769 
770  cfmakeraw(&tty_setting);
771  tty_setting.c_cc[VMIN] = 1;
772  tty_setting.c_cc[VTIME] = 10;
773 
774  // The baud rate, word length, and handshake options can be set as follows:
775  switch (bit_rate)
776  {
777  case 0: bps = B0; break;
778  case 50: bps = B50; break;
779  case 75: bps = B75; break;
780  case 110: bps = B110; break;
781  case 134: bps = B134; break;
782  case 150: bps = B150; break;
783  case 200: bps = B200; break;
784  case 300: bps = B300; break;
785  case 600: bps = B600; break;
786  case 1200: bps = B1200; break;
787  case 1800: bps = B1800; break;
788  case 2400: bps = B2400; break;
789  case 4800: bps = B4800; break;
790  case 9600: bps = B9600; break;
791  case 19200: bps = B19200; break;
792  case 38400: bps = B38400; break;
793  case 57600: bps = B57600; break;
794  case 115200: bps = B115200; break;
795  case 230400: bps = B230400; break;
796 #if !defined(__APPLE__) && !defined(__FreeBSD__)
797  case 460800: bps = B460800; break;
798  case 576000: bps = B576000; break;
799  case 921600: bps = B921600; break;
800 #endif
801  default:
802  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) < 0)
803  perror(NULL);
804  else
805  perror(msg);
806  return TTY_PARAM_ERROR;
807  }
808 
809  cfsetspeed(&tty_setting, bps); // Set baud rate
810  /* word size */
811  switch (word_size)
812  {
813  case 5: tty_setting.c_cflag |= CS5; break;
814  case 6: tty_setting.c_cflag |= CS6; break;
815  case 7: tty_setting.c_cflag |= CS7; break;
816  case 8: tty_setting.c_cflag |= CS8; break;
817  default:
818  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) < 0)
819  perror(NULL);
820  else
821  perror(msg);
822 
823  return TTY_PARAM_ERROR;
824  }
825 
826  /* parity */
827  switch (parity)
828  {
829  case PARITY_NONE:
830  break;
831  case PARITY_EVEN:
832  tty_setting.c_cflag |= PARENB;
833  break;
834  case PARITY_ODD:
835  tty_setting.c_cflag |= PARENB | PARODD;
836  break;
837  default:
838  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) < 0)
839  perror(NULL);
840  else
841  perror(msg);
842 
843  return TTY_PARAM_ERROR;
844  }
845 
846  /* stop_bits */
847  switch (stop_bits)
848  {
849  case 1:
850  break;
851  case 2:
852  tty_setting.c_cflag |= CSTOPB;
853  break;
854  default:
855  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) < 0)
856  perror(NULL);
857  else
858  perror(msg);
859 
860  return TTY_PARAM_ERROR;
861  }
862 
863 #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
864  // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
865  // other than those specified by POSIX. The driver for the underlying serial hardware
866  // ultimately determines which baud rates can be used. This ioctl sets both the input
867  // and output speed.
868 
869  speed_t speed = 14400; // Set 14400 baud
870  if (ioctl(t_fd, IOSSIOSPEED, &speed) == -1)
871  {
872  IDLog("Error calling ioctl(..., IOSSIOSPEED, ...) - %s(%d).\n", strerror(errno), errno);
873  }
874 #endif
875 
876  // Cause the new options to take effect immediately.
877  if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
878  {
879  IDLog("Error setting tty attributes %s - %s(%d).\n", device, strerror(errno), errno);
880  goto error;
881  }
882 
883  // To set the modem handshake lines, use the following ioctls.
884  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
885 
886  if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
887  {
888  IDLog("Error asserting DTR %s - %s(%d).\n", device, strerror(errno), errno);
889  }
890 
891  if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
892  {
893  IDLog("Error clearing DTR %s - %s(%d).\n", device, strerror(errno), errno);
894  }
895 
896  handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
897  if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
898  // Set the modem lines depending on the bits set in handshake
899  {
900  IDLog("Error setting handshake lines %s - %s(%d).\n", device, strerror(errno), errno);
901  }
902 
903  // To read the state of the modem lines, use the following ioctl.
904  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
905 
906  if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
907  // Store the state of the modem lines in handshake
908  {
909  IDLog("Error getting handshake lines %s - %s(%d).\n", device, strerror(errno), errno);
910  }
911 
912  IDLog("Handshake lines currently set to %d\n", handshake);
913 
914 #if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
915  unsigned long mics = 1UL;
916 
917  // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
918  // dequeue characters received by the hardware. Most applications don't need to set this value: if an
919  // app reads lines of characters, the app can't do anything until the line termination character has been
920  // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
921  // applications.
922 
923  if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
924  {
925  // set latency to 1 microsecond
926  IDLog("Error setting read latency %s - %s(%d).\n", device, strerror(errno), errno);
927  goto error;
928  }
929 #endif
930 
931  *fd = t_fd;
932  /* return success */
933  return TTY_OK;
934 
935  // Failure path
936 error:
937  if (t_fd != -1)
938  {
939  close(t_fd);
940  *fd = -1;
941  }
942 
943  return TTY_PORT_FAILURE;
944 }
945 #else
946 int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
947 {
948 #ifdef _WIN32
949  return TTY_PORT_FAILURE;
950 
951 #else
952  int t_fd = -1;
953  int i = 0;
954  char msg[128]={0};
955  int bps;
956  struct termios tty_setting;
957  // Check for bluetooth & virtualcom which can be shared
958  int ignore_exclusive_close = strstr(device, "rfcomm") || strstr(device, "Bluetooth") || strstr(device, "virtualcom");
959 
960 
961  // Open as Read/Write, no fnctl, and close on exclusive
962  for (i = 0 ; i < 3 ; i++)
963  {
964  // Do not use O_CLOEXEC when ignored
965  t_fd = open(device, O_RDWR | O_NOCTTY | (ignore_exclusive_close ? 0 : O_CLOEXEC));
966  if (t_fd > 0)
967  break;
968  else
969  {
970  *fd = -1;
971  if (errno == EBUSY)
972  {
973  usleep(1e6);
974  continue;
975  }
976  else
977  return TTY_PORT_FAILURE;
978  }
979  }
980 
981  if (t_fd == -1)
982  return TTY_PORT_BUSY;
983 
984 #if !defined(__CYGWIN__)
985  // Set port in exclusive mode to prevent other non-root processes from opening it.
986  // JM 2019-08-12: Do not set it when ignored
987  if (ignore_exclusive_close == 0 && ioctl(t_fd, TIOCEXCL) == -1)
988  {
989  perror("tty_connect: Error setting TIOCEXC.");
990  close(t_fd);
991  return TTY_PORT_FAILURE;
992  }
993 #endif
994 
995  // Get the current options and save them so we can restore the default settings later.
996  if (tcgetattr(t_fd, &tty_setting) == -1)
997  {
998  perror("tty_connect: failed getting tty attributes.");
999  close(t_fd);
1000  return TTY_PORT_FAILURE;
1001  }
1002 
1003  /* Control Modes
1004  Set bps rate */
1005  switch (bit_rate)
1006  {
1007  case 0: bps = B0; break;
1008  case 50: bps = B50; break;
1009  case 75: bps = B75; break;
1010  case 110: bps = B110; break;
1011  case 134: bps = B134; break;
1012  case 150: bps = B150; break;
1013  case 200: bps = B200; break;
1014  case 300: bps = B300; break;
1015  case 600: bps = B600; break;
1016  case 1200: bps = B1200; break;
1017  case 1800: bps = B1800; break;
1018  case 2400: bps = B2400; break;
1019  case 4800: bps = B4800; break;
1020  case 9600: bps = B9600; break;
1021  case 19200: bps = B19200; break;
1022  case 38400: bps = B38400; break;
1023  case 57600: bps = B57600; break;
1024  case 115200: bps = B115200; break;
1025  case 230400: bps = B230400; break;
1026  case 460800: bps = B460800; break;
1027  case 576000: bps = B576000; break;
1028  case 921600: bps = B921600; break;
1029  default:
1030  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) < 0)
1031  perror(NULL);
1032  else
1033  perror(msg);
1034  close(t_fd);
1035  return TTY_PARAM_ERROR;
1036  }
1037  if ((cfsetispeed(&tty_setting, bps) < 0) || (cfsetospeed(&tty_setting, bps) < 0))
1038  {
1039  perror("tty_connect: failed setting bit rate.");
1040  close(t_fd);
1041  return TTY_PORT_FAILURE;
1042  }
1043 
1044  /* Control Modes
1045  set no flow control word size, parity and stop bits.
1046  Also don't hangup automatically and ignore modem status.
1047  Finally enable receiving characters. */
1048  tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
1049  tty_setting.c_cflag |= (CLOCAL | CREAD);
1050 
1051  /* word size */
1052  switch (word_size)
1053  {
1054  case 5: tty_setting.c_cflag |= CS5; break;
1055  case 6: tty_setting.c_cflag |= CS6; break;
1056  case 7: tty_setting.c_cflag |= CS7; break;
1057  case 8: tty_setting.c_cflag |= CS8; break;
1058  default:
1059 
1060  fprintf(stderr, "Default\n");
1061  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) < 0)
1062  perror(NULL);
1063  else
1064  perror(msg);
1065 
1066  close(t_fd);
1067  return TTY_PARAM_ERROR;
1068  }
1069 
1070  /* parity */
1071  switch (parity)
1072  {
1073  case PARITY_NONE:
1074  break;
1075  case PARITY_EVEN:
1076  tty_setting.c_cflag |= PARENB;
1077  break;
1078  case PARITY_ODD:
1079  tty_setting.c_cflag |= PARENB | PARODD;
1080  break;
1081  default:
1082 
1083  fprintf(stderr, "Default1\n");
1084  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) < 0)
1085  perror(NULL);
1086  else
1087  perror(msg);
1088 
1089  close(t_fd);
1090  return TTY_PARAM_ERROR;
1091  }
1092 
1093  /* stop_bits */
1094  switch (stop_bits)
1095  {
1096  case 1:
1097  break;
1098  case 2:
1099  tty_setting.c_cflag |= CSTOPB;
1100  break;
1101  default:
1102  fprintf(stderr, "Default2\n");
1103  if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) < 0)
1104  perror(NULL);
1105  else
1106  perror(msg);
1107 
1108  close(t_fd);
1109  return TTY_PARAM_ERROR;
1110  }
1111  /* Control Modes complete */
1112 
1113  /* Ignore bytes with parity errors and make terminal raw and dumb.*/
1114  tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
1115  tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
1116 
1117  /* Raw output.*/
1118  tty_setting.c_oflag &= ~(OPOST | ONLCR);
1119 
1120  /* Local Modes
1121  Don't echo characters. Don't generate signals.
1122  Don't process any characters.*/
1123  tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
1124  tty_setting.c_lflag |= NOFLSH;
1125 
1126  /* blocking read until 1 char arrives */
1127  tty_setting.c_cc[VMIN] = 1;
1128  tty_setting.c_cc[VTIME] = 0;
1129 
1130  /* now clear input and output buffers and activate the new terminal settings */
1131  tcflush(t_fd, TCIOFLUSH);
1132  if (tcsetattr(t_fd, TCSANOW, &tty_setting))
1133  {
1134  perror("tty_connect: failed setting attributes on serial port.");
1135  tty_disconnect(t_fd);
1136  return TTY_PORT_FAILURE;
1137  }
1138 
1139  *fd = t_fd;
1140  /* return success */
1141  return TTY_OK;
1142 #endif
1143 }
1144 // Unix - Linux version
1145 
1146 #endif
1147 
1149 {
1150  if (fd == -1)
1151  return TTY_ERRNO;
1152 
1153 #ifdef _WIN32
1154  return TTY_ERRNO;
1155 #else
1156  int err;
1157  tcflush(fd, TCIOFLUSH);
1158  err = close(fd);
1159 
1160  if (err != 0)
1161  return TTY_ERRNO;
1162 
1163  return TTY_OK;
1164 #endif
1165 }
1166 
1167 void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
1168 {
1169  switch (err_code)
1170  {
1171  case TTY_OK:
1172  snprintf(err_msg, err_msg_len, "No Error");
1173  break;
1174 
1175  case TTY_READ_ERROR:
1176  snprintf(err_msg, err_msg_len, "Read Error: %s", strerror(errno));
1177  break;
1178 
1179  case TTY_WRITE_ERROR:
1180  snprintf(err_msg, err_msg_len, "Write Error: %s", strerror(errno));
1181  break;
1182 
1183  case TTY_SELECT_ERROR:
1184  snprintf(err_msg, err_msg_len, "Select Error: %s", strerror(errno));
1185  break;
1186 
1187  case TTY_TIME_OUT:
1188  snprintf(err_msg, err_msg_len, "Timeout error");
1189  break;
1190 
1191  case TTY_PORT_FAILURE:
1192  if (errno == EACCES)
1193  snprintf(err_msg, err_msg_len,
1194  "Port failure Error: %s. Try adding your user to the dialout group and restart (sudo adduser "
1195  "$USER dialout)",
1196  strerror(errno));
1197  else
1198  snprintf(err_msg, err_msg_len, "Port failure Error: %s. Check if device is connected to this port.",
1199  strerror(errno));
1200 
1201  break;
1202 
1203  case TTY_PARAM_ERROR:
1204  snprintf(err_msg, err_msg_len, "Parameter error");
1205  break;
1206 
1207  case TTY_ERRNO:
1208  snprintf(err_msg, err_msg_len, "%s", strerror(errno));
1209  break;
1210 
1211  case TTY_OVERFLOW:
1212  snprintf(err_msg, err_msg_len, "Read overflow");
1213  break;
1214 
1215  case TTY_PORT_BUSY:
1216  snprintf(err_msg, err_msg_len, "Port is busy");
1217  break;
1218 
1219  default:
1220  snprintf(err_msg, err_msg_len, "Error: unrecognized error code");
1221  break;
1222  }
1223 }
1224 
1225 double rangeHA(double r)
1226 {
1227  double res = r;
1228  while (res < -12.0)
1229  res += 24.0;
1230  while (res >= 12.0)
1231  res -= 24.0;
1232  return res;
1233 }
1234 
1235 double range24(double r)
1236 {
1237  double res = r;
1238  while (res < 0.0)
1239  res += 24.0;
1240  while (res > 24.0)
1241  res -= 24.0;
1242  return res;
1243 }
1244 
1245 double range360(double r)
1246 {
1247  double res = r;
1248  while (res < 0.0)
1249  res += 360.0;
1250  while (res > 360.0)
1251  res -= 360.0;
1252  return res;
1253 }
1254 
1255 double rangeDec(double decdegrees)
1256 {
1257  if ((decdegrees >= 270.0) && (decdegrees <= 360.0))
1258  return (decdegrees - 360.0);
1259  if ((decdegrees >= 180.0) && (decdegrees < 270.0))
1260  return (180.0 - decdegrees);
1261  if ((decdegrees >= 90.0) && (decdegrees < 180.0))
1262  return (180.0 - decdegrees);
1263  return decdegrees;
1264 }
1265 
1266 #if defined(HAVE_LIBNOVA)
1267 double get_local_sidereal_time(double longitude)
1268 {
1269  return range24(ln_get_apparent_sidereal_time(ln_get_julian_from_sys()) + longitude / 15.0);
1270 }
1271 
1272 void get_hrz_from_equ(struct ln_equ_posn *object, struct ln_lnlat_posn *observer, double JD, struct ln_hrz_posn *position)
1273 {
1274  ln_get_hrz_from_equ(object, observer, JD, position);
1275  position->az -= 180;
1276  if (position->az < 0)
1277  position->az += 360;
1278 }
1279 
1280 void get_equ_from_hrz(struct ln_hrz_posn *object, struct ln_lnlat_posn *observer, double JD, struct ln_equ_posn *position)
1281 {
1282  struct ln_hrz_posn libnova_object;
1283  libnova_object.az = object->az + 180;
1284  if (libnova_object.az > 360)
1285  libnova_object.az -= 360;
1286  libnova_object.alt = object->alt;
1287 
1288  ln_get_equ_from_hrz(&libnova_object, observer, JD, position);
1289 }
1290 
1291 #endif // HAVE_LIBNOVA
1292 
1293 double get_local_hour_angle(double sideral_time, double ra)
1294 {
1295  double HA = sideral_time - ra;
1296  return rangeHA(HA);
1297 }
1298 
1299 void get_alt_az_coordinates(double Ha, double Dec, double Lat, double* Alt, double *Az)
1300 {
1301  double alt, az;
1302  Ha *= M_PI / 180.0;
1303  Dec *= M_PI / 180.0;
1304  Lat *= M_PI / 180.0;
1305  alt = asin(sin(Dec) * sin(Lat) + cos(Dec) * cos(Lat) * cos(Ha));
1306  az = acos((sin(Dec) - sin(alt)*sin(Lat)) / (cos(alt) * cos(Lat)));
1307  alt *= 180.0 / M_PI;
1308  az *= 180.0 / M_PI;
1309  if (sin(Ha) >= 0.0)
1310  az = 360 - az;
1311  *Alt = alt;
1312  *Az = az;
1313 }
1314 
1315 double estimate_geocentric_elevation(double Lat, double El)
1316 {
1317  Lat *= M_PI / 180.0;
1318  Lat = sin(Lat);
1319  El += Lat * (EARTHRADIUSPOLAR - EARTHRADIUSEQUATORIAL);
1320  return El;
1321 }
1322 
1323 double estimate_field_rotation_rate(double Alt, double Az, double Lat)
1324 {
1325  Alt *= M_PI / 180.0;
1326  Az *= M_PI / 180.0;
1327  Lat *= M_PI / 180.0;
1328  double ret = cos(Lat) * cos(Az) / cos(Alt);
1329  ret *= 180.0 / M_PI;
1330  return ret;
1331 }
1332 
1333 double estimate_field_rotation(double HA, double rate)
1334 {
1335  HA *= rate;
1336  while(HA >= 360.0)
1337  HA -= 360.0;
1338  while(HA < 0)
1339  HA += 360.0;
1340  return HA;
1341 }
1342 
1343 double as2rad(double as)
1344 {
1345  return as * M_PI / (60.0*60.0*12.0);
1346 }
1347 
1348 double rad2as(double rad)
1349 {
1350  return rad * (60.0*60.0*12.0) / M_PI;
1351 }
1352 
1353 double estimate_distance(double parsecs, double parallax_radius)
1354 {
1355  return parallax_radius / sin(as2rad(parsecs));
1356 }
1357 
1358 double m2au(double m)
1359 {
1360  return m / ASTRONOMICALUNIT;
1361 }
1362 
1363 double calc_delta_magnitude(double mag_ratio, double *spectrum, double *ref_spectrum, int spectrum_size)
1364 {
1365  double delta_mag = 0;
1366  for(int l = 0; l < spectrum_size; l++) {
1367  delta_mag += spectrum[l] * mag_ratio * ref_spectrum[l] / spectrum[l];
1368  }
1369  delta_mag /= spectrum_size;
1370  return delta_mag;
1371 }
1372 
1373 double calc_star_mass(double delta_mag, double ref_size)
1374 {
1375  return delta_mag * ref_size;
1376 }
1377 
1378 double estimate_orbit_radius(double obs_lambda, double ref_lambda, double period)
1379 {
1380  return M_PI*2*DOPPLER(REDSHIFT(obs_lambda, ref_lambda), LIGHTSPEED)/period;
1381 }
1382 
1383 double estimate_secondary_mass(double star_mass, double star_drift, double orbit_radius)
1384 {
1385  return orbit_radius*pow(star_drift*orbit_radius, 3)*3*star_mass;
1386 }
1387 
1388 double estimate_secondary_size(double star_size, double dropoff_ratio)
1389 {
1390  return pow(dropoff_ratio*pow(star_size, 2), 0.5);
1391 }
1392 
1393 double calc_photon_flux(double rel_magnitude, double filter_bandwidth, double wavelength, double steradian)
1394 {
1395  return pow(10, rel_magnitude*-0.4)*(LUMEN(wavelength)*steradian*filter_bandwidth);
1396 }
1397 
1398 double calc_rel_magnitude(double photon_flux, double filter_bandwidth, double wavelength, double steradian)
1399 {
1400  return pow(10, 1.0/(photon_flux/(LUMEN(wavelength)*steradian*filter_bandwidth)))/-0.4;
1401 }
1402 
1403 double estimate_absolute_magnitude(double delta_dist, double delta_mag)
1404 {
1405  return sqrt(delta_dist) * delta_mag;
1406 }
1407 
1408 void baseline_2d_projection(double alt, double az, double baseline[3], double wavelength, double uvresult[2])
1409 {
1410  az *= M_PI / 180.0;
1411  alt *= M_PI / 180.0;
1412  uvresult[0] = (baseline[0] * sin(az) + baseline[1] * cos(az));
1413  uvresult[1] = (baseline[1] * sin(alt) * sin(az) - baseline[0] * sin(alt) * cos(az) + baseline[2] * cos(alt));
1414  uvresult[0] *= AIRY / wavelength;
1415  uvresult[1] *= AIRY / wavelength;
1416 }
1417 
1418 double baseline_delay(double alt, double az, double baseline[3])
1419 {
1420  az *= M_PI / 180.0;
1421  alt *= M_PI / 180.0;
1422  return cos(az) * baseline[1] * cos(alt) - baseline[0] * sin(az) * cos(alt) + sin(alt) * baseline[2];
1423 }
1424 
1425 #if defined(_MSC_VER)
1426 #undef snprintf
1427 #pragma warning(pop)
1428 #endif
hid_device * device
int errno
double ra
#define MAXINDIFORMAT
Definition: indiapi.h:195
void get_alt_az_coordinates(double Ha, double Dec, double Lat, double *Alt, double *Az)
get_alt_az_coordinates Returns alt-azimuth coordinates of an object
Definition: indicom.c:1299
double estimate_secondary_size(double star_size, double dropoff_ratio)
estimate the size of an object occulting a star in star_size units.
Definition: indicom.c:1388
void tty_set_generic_udp_format(int enabled)
Definition: indicom.c:370
double calc_rel_magnitude(double photon_flux, double filter_bandwidth, double wavelength, double steradian)
calc_rel_magnitude Returns the relative magnitude of the object with the given photon flux measured a...
Definition: indicom.c:1398
double estimate_secondary_mass(double star_mass, double star_drift, double orbit_radius)
estimate the mass of an object with known mass orbiting around a star.
Definition: indicom.c:1383
void baseline_2d_projection(double alt, double az, double baseline[3], double wavelength, double uvresult[2])
baseline_2d_projection Returns the coordinates of the projection of a single baseline targeting the o...
Definition: indicom.c:1408
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:566
void getSexComponentsIID(double value, int *d, int *m, double *s)
Definition: indicom.c:277
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double. x can be anything non-numeric. Any missing A,...
Definition: indicom.c:205
int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
Establishes a tty connection to a terminal device.
Definition: indicom.c:946
double calc_photon_flux(double rel_magnitude, double filter_bandwidth, double wavelength, double steradian)
calc_photon_flux Returns the photon flux of the object with the given magnitude observed at a determi...
Definition: indicom.c:1393
#define PARITY_ODD
Definition: indicom.c:89
void tty_set_debug(int debug)
tty_set_debug Enable or disable debug which prints verbose information.
Definition: indicom.c:360
double estimate_distance(double parsecs, double parallax_radius)
estimate_distance Convert parallax arcseconds into meters
Definition: indicom.c:1353
double estimate_absolute_magnitude(double delta_dist, double delta_mag)
estimate_absolute_magnitude Returns an estimation of the absolute magnitude of an object given its di...
Definition: indicom.c:1403
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:424
double estimate_field_rotation(double HA, double rate)
estimate_field_rotation Returns an estimation of the field rotation rate of the object
Definition: indicom.c:1333
double estimate_orbit_radius(double obs_lambda, double ref_lambda, double period)
estimate the orbit radius of an object with known mass orbiting around a star.
Definition: indicom.c:1378
int tty_disconnect(int fd)
Closes a tty connection and flushes the bus.
Definition: indicom.c:1148
void IDLog(const char *fmt,...)
Definition: indicom.c:316
#define PARITY_EVEN
Definition: indicom.c:88
double estimate_field_rotation_rate(double Alt, double Az, double Lat)
estimate_field_rotation_rate Returns an estimation of the field rotation rate of the object
Definition: indicom.c:1323
int tty_timeout_microseconds(int fd, long timeout_seconds, long timeout_microseconds)
Definition: indicom.c:385
double rangeHA(double r)
rangeHA Limits the hour angle value to be between -12 —> 12
Definition: indicom.c:1225
void getSexComponents(double value, int *d, int *m, int *s)
Definition: indicom.c:254
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:482
#define PARITY_NONE
Definition: indicom.c:87
double calc_star_mass(double delta_mag, double ref_size)
Definition: indicom.c:1373
double m2au(double m)
m2au Convert meters into astronomical units
Definition: indicom.c:1358
const char * indi_timestamp()
Create an ISO 8601 formatted time stamp. The format is YYYY-MM-DDTHH:MM:SS.
Definition: indicom.c:348
double range24(double r)
range24 Limits a number to be between 0-24 range.
Definition: indicom.c:1235
int tty_read_section_expanded(int fd, char *buf, char stop_char, long timeout_seconds, long timeout_microseconds, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:571
int tty_timeout(int fd, int timeout)
Definition: indicom.c:380
double as2rad(double as)
as2rad Convert arcseconds into radians
Definition: indicom.c:1343
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
Definition: indicom.c:1245
double rangeDec(double decdegrees)
rangeDec Limits declination value to be in -90 to 90 range.
Definition: indicom.c:1255
double baseline_delay(double alt, double az, double baseline[3])
baseline_delay Returns the delay in meters of a single baseline targeting the object by coordinates
Definition: indicom.c:1418
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
double time_ns()
Get a unix timestamp with nanosecond precision.
Definition: indicom.c:326
double calc_delta_magnitude(double mag_ratio, double *spectrum, double *ref_spectrum, int spectrum_size)
calc_delta_magnitude Returns the difference of magnitudes given two spectra
Definition: indicom.c:1363
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string. sprint the variable a in sexagesimal format into out[].
Definition: indicom.c:141
int numberFormat(char *buf, const char *format, double value)
Fill buffer with properly formatted INumber string.
Definition: indicom.c:288
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:666
int tty_read_expanded(int fd, char *buf, int nbytes, long timeout_seconds, long timeout_microseconds, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:487
void tty_clr_trailing_read_lf(int enabled)
Definition: indicom.c:375
void tty_set_gemini_udp_format(int enabled)
Definition: indicom.c:365
double get_local_hour_angle(double sideral_time, double ra)
get_local_hour_angle Returns local hour angle of an object
Definition: indicom.c:1293
double estimate_geocentric_elevation(double Lat, double El)
estimate_geocentric_elevation Returns an estimation of the actual geocentric elevation
Definition: indicom.c:1315
double rad2as(double rad)
rad2as Convert radians into arcseconds
Definition: indicom.c:1348
Implementations for common driver routines.
@ TTY_PORT_FAILURE
Definition: indicom.h:155
@ TTY_OK
Definition: indicom.h:150
@ TTY_READ_ERROR
Definition: indicom.h:151
@ TTY_SELECT_ERROR
Definition: indicom.h:153
@ TTY_TIME_OUT
Definition: indicom.h:154
@ TTY_PORT_BUSY
Definition: indicom.h:159
@ TTY_PARAM_ERROR
Definition: indicom.h:156
@ TTY_OVERFLOW
Definition: indicom.h:158
@ TTY_WRITE_ERROR
Definition: indicom.h:152
@ TTY_ERRNO
Definition: indicom.h:157
double get_local_sidereal_time(double longitude)
get_local_sidereal_time Returns local sideral time given longitude and system clock.
#define LUMEN(wavelength)
Definition: indicom.h:130
#define DOPPLER(shift, speed)
Definition: indicom.h:136
#define EARTHRADIUSEQUATORIAL
Definition: indicom.h:67
#define AIRY
Definition: indicom.h:94
void get_hrz_from_equ(struct ln_equ_posn *object, struct ln_lnlat_posn *observer, double JD, struct ln_hrz_posn *position)
get_hrz_from_equ Calculate horizontal coordinates from equatorial coordinates.
#define EARTHRADIUSPOLAR
Definition: indicom.h:70
#define REDSHIFT(wavelength, reference)
Definition: indicom.h:133
int extractISOTime(const char *timestr, struct ln_date *iso_date)
Extract ISO 8601 time and store it in a tm struct.
void get_equ_from_hrz(struct ln_hrz_posn *object, struct ln_lnlat_posn *observer, double JD, struct ln_equ_posn *position)
ln_get_equ_from_hrz Calculate Equatorial EOD Coordinates from horizontal coordinates
#define LIGHTSPEED
Definition: indicom.h:115
#define ASTRONOMICALUNIT
Definition: indicom.h:109
Interface to the reference INDI C API device implementation on the Device Driver side.
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int fd
Definition: intelliscope.c:43
char locale_char_t
Definition: locale_compat.h:62
std::vector< uint8_t > buffer
@ error
throw a parse_error exception in case of a tag
struct termios tty_setting
Definition: stvdriver.c:51