Instrument Neutral Distributed Interface INDI  2.0.2
magellan1.cpp
Go to the documentation of this file.
1 #if 0
2 MAGELLAN Generic
3 Copyright (C) 2011 Onno Hommes (ohommes@alumni.cmu.edu)
4 
5 This library is free software;
6 you can redistribute it and / or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation;
9 either
10 version 2.1 of the License, or (at your option) any later version.
11 
12 This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY;
14 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;
20 if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA
22 
23 #endif
24 
25 #include "magellan1.h"
26 
27 #include "magellandriver.h"
28 
29 #include <memory>
30 
31 extern char *me;
32 
33 #define COMM_GROUP "Communication"
34 #define BASIC_GROUP "Position"
35 
36 #define MAGELLAN_TRACK 0
37 #define MAGELLAN_SYNC 1
38 
39 /* Handy Macros */
40 #define currentRA EquatorialCoordsRN[0].value
41 #define currentDEC EquatorialCoordsRN[1].value
42 
43 static void ISPoll(void *);
44 static void retryConnection(void *);
45 
46 /*INDI Propertries */
47 
48 /**********************************************************************************************/
49 /************************************ GROUP: Communication ************************************/
50 /**********************************************************************************************/
51 
52 /********************************************
53  Property: Connection
54 *********************************************/
55 static ISwitch ConnectS[] = { { "CONNECT", "Connect", ISS_OFF, 0, 0 }, { "DISCONNECT", "Disconnect", ISS_ON, 0, 0 } };
56 ISwitchVectorProperty ConnectSP = { mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY,
57  0, IPS_IDLE, ConnectS, NARRAY(ConnectS), "", 0
58  };
59 
60 /********************************************
61  Property: Device Port
62 *********************************************/
63 /*wildi removed static */
64 static IText PortT[] = { { "PORT", "Port", 0, 0, 0, 0 } };
65 ITextVectorProperty PortTP = { mydev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0,
66  IPS_IDLE, PortT, NARRAY(PortT), "", 0
67  };
68 
69 /**********************************************************************************************/
70 /************************************ GROUP: Position Display**********************************/
71 /**********************************************************************************************/
72 
73 /********************************************
74  Property: Equatorial Coordinates JNow
75  Perm: RO
76 *********************************************/
77 INumber EquatorialCoordsRN[] = { { "RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0., 0, 0, 0 },
78  { "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0 }
79 };
81 {
82  mydev, "EQUATORIAL_EOD_COORD", "Equatorial JNow", BASIC_GROUP, IP_RO, 120,
84 };
85 
86 /*****************************************************************************************************/
87 /**************************************** END PROPERTIES *********************************************/
88 /*****************************************************************************************************/
89 
90 static class Loader
91 {
92  Magellan1 *telescope = nullptr;
93  std::unique_ptr<Magellan1> telescope;
94  public:
95  Loader()
96  {
97  IUSaveText(&PortT[0], "/dev/ttyS0");
98  telescope.reset(new Magellan1());
99  telescope->setCurrentDeviceName(mydev);
100  IEAddTimer(POLLMS, ISPoll, nullptr);
101  }
102 } loader;
103 
104 /**************************************************
105 *** MAGELLAN1 Implementation
106 ***************************************************/
107 
109 {
110  currentSiteNum = 1;
112  lastSet = -1;
113  fault = false;
114  simulation = false;
115  currentSet = 0;
116  fd = -1;
117 
118  // Children call parent routines, this is the default
119  IDLog("Initializing from MAGELLAN device...\n");
120  IDLog("Driver Version: 2011-07-28\n");
121 }
122 
124 {
125 }
126 
127 void Magellan1::setCurrentDeviceName(const char *devName)
128 {
129  strcpy(thisDevice, devName);
130 }
131 
132 void Magellan1::ISGetProperties(const char *dev)
133 {
134  if (dev != nullptr && strcmp(thisDevice, dev))
135  return;
136 
137  // COMM_GROUP
138  IDDefSwitch(&ConnectSP, nullptr);
139  IDDefText(&PortTP, nullptr);
140 
141  // POSITION_GROUP
142  IDDefNumber(&EquatorialCoordsRNP, nullptr);
143 
144  /* Send the basic data to the new client if the previous client(s) are already connected. */
145  if (ConnectSP.s == IPS_OK)
146  getBasicData();
147 }
148 
150 {
151  INDI_UNUSED(root);
152 }
153 
154 void Magellan1::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
155 {
156  IText *tp;
157 
158  /* Ignore other devices */
159  if (strcmp(dev, thisDevice))
160  return;
161 
162  /* See if the port is updated */
163  if (!strcmp(name, PortTP.name))
164  {
165  PortTP.s = IPS_OK;
166  tp = IUFindText(&PortTP, names[0]);
167  if (!tp)
168  return;
169 
170  IUSaveText(&PortTP.tp[0], texts[0]);
171  IDSetText(&PortTP, nullptr);
172  return;
173  }
174 }
175 
176 void Magellan1::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
177 {
178  INDI_UNUSED(dev);
179  INDI_UNUSED(name);
180  INDI_UNUSED(values);
181  INDI_UNUSED(names);
182  INDI_UNUSED(n);
183 }
184 
185 void Magellan1::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
186 {
187  INDI_UNUSED(names);
188 
189  /* Ignore other devices */
190  if (strcmp(thisDevice, dev))
191  return;
192 
193  // FIRST Switch ALWAYS for Connection
194  if (!strcmp(name, ConnectSP.name))
195  {
196  bool connectionEstablished = (ConnectS[0].s == ISS_ON);
197  if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
198  return;
199  if ((connectionEstablished && ConnectS[0].s == ISS_ON) || (!connectionEstablished && ConnectS[1].s == ISS_ON))
200  {
201  ConnectSP.s = IPS_OK;
202  IDSetSwitch(&ConnectSP, nullptr);
203  return;
204  }
206  return;
207  }
208 }
209 
210 void Magellan1::handleError(ISwitchVectorProperty *svp, int err, const char *msg)
211 {
212  svp->s = IPS_ALERT;
213 
214  /* First check to see if the telescope is connected */
216  {
217  /* The telescope is off locally */
218  ConnectS[0].s = ISS_OFF;
219  ConnectS[1].s = ISS_ON;
220  ConnectSP.s = IPS_BUSY;
221  IDSetSwitch(&ConnectSP, "Telescope is not responding to commands, will retry in 10 seconds.");
222 
223  IDSetSwitch(svp, nullptr);
224  IEAddTimer(10000, retryConnection, &fd);
225  return;
226  }
227 
228  /* If the error is a time out, then the device doesn't support this property or busy*/
229  if (err == -2)
230  {
231  svp->s = IPS_ALERT;
232  IDSetSwitch(svp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
233  }
234  else
235  /* Changing property failed, user should retry. */
236  IDSetSwitch(svp, "%s failed.", msg);
237 
238  fault = true;
239 }
240 
241 void Magellan1::handleError(INumberVectorProperty *nvp, int err, const char *msg)
242 {
243  nvp->s = IPS_ALERT;
244 
245  /* First check to see if the telescope is connected */
247  {
248  /* The telescope is off locally */
249  ConnectS[0].s = ISS_OFF;
250  ConnectS[1].s = ISS_ON;
251  ConnectSP.s = IPS_BUSY;
252  IDSetSwitch(&ConnectSP, "Telescope is not responding to commands, will retry in 10 seconds.");
253 
254  IDSetNumber(nvp, nullptr);
255  IEAddTimer(10000, retryConnection, &fd);
256  return;
257  }
258 
259  /* If the error is a time out, then the device doesn't support this property */
260  if (err == -2)
261  {
262  nvp->s = IPS_ALERT;
263  IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
264  }
265  else
266  /* Changing property failed, user should retry. */
267  IDSetNumber(nvp, "%s failed.", msg);
268 
269  fault = true;
270 }
271 
272 void Magellan1::handleError(ITextVectorProperty *tvp, int err, const char *msg)
273 {
274  tvp->s = IPS_ALERT;
275 
276  /* First check to see if the telescope is connected */
278  {
279  /* The telescope is off locally */
280  ConnectS[0].s = ISS_OFF;
281  ConnectS[1].s = ISS_ON;
282  ConnectSP.s = IPS_BUSY;
283  IDSetSwitch(&ConnectSP, "Telescope is not responding to commands, will retry in 10 seconds.");
284 
285  IDSetText(tvp, nullptr);
286  IEAddTimer(10000, retryConnection, &fd);
287  return;
288  }
289 
290  /* If the error is a time out, then the device doesn't support this property */
291  if (err == -2)
292  {
293  tvp->s = IPS_ALERT;
294  IDSetText(tvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
295  }
296 
297  else
298  {
299  /* Changing property failed, user should retry. */
300  IDSetText(tvp, "%s failed.", msg);
301  }
302 
303  fault = true;
304 }
305 
307 {
308  fault = false;
309  IDMessage(thisDevice, "Telescope is online.");
310 }
311 
313 {
314  return (ConnectSP.sp[0].s == ISS_ON);
315 }
316 
317 static void retryConnection(void *p)
318 {
319  int fd = *((int *)p);
320 
322  {
323  ConnectSP.s = IPS_IDLE;
324  IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
325  return;
326  }
327 
328  ConnectS[0].s = ISS_ON;
329  ConnectS[1].s = ISS_OFF;
330  ConnectSP.s = IPS_OK;
331 
332  IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
333 }
334 
336 {
337  int err = 0;
338 
339  if (!isTelescopeOn())
340  return;
341 
342  if ((err = getMAGELLANRA(fd, &currentRA)) < 0 || (err = getMAGELLANDEC(fd, &currentDEC)) < 0)
343  {
345  IDSetNumber(&EquatorialCoordsRNP, nullptr);
346  handleError(&EquatorialCoordsRNP, err, "Getting RA/DEC");
347  return;
348  }
349 
350  if (fault)
351  correctFault();
352 
354 
355  lastRA = currentRA;
357  IDSetNumber(&EquatorialCoordsRNP, nullptr);
358 }
359 
361 {
362  char calendarDate[32];
363  int err;
364 
365  /* Magellan 1 Get Calendar Date As a Test (always 1/1/96) */
366  if ((err = getCalendarDate(fd, calendarDate)) < 0)
367  IDMessage(thisDevice, "Failed to retrieve calendar date from device.");
368  else
369  IDMessage(thisDevice, "Successfully retrieved calendar date from device.");
370 
371  /* Only 24 Time format on Magellan and you cant get to the local time
372  which you can set in Magellan I */
374 
375  if ((err = getMAGELLANRA(fd, &targetRA)) < 0 || (err = getMAGELLANDEC(fd, &targetDEC)) < 0)
376  {
378  IDSetNumber(&EquatorialCoordsRNP, nullptr);
379  handleError(&EquatorialCoordsRNP, err, "Getting RA/DEC");
380  return;
381  }
382 
383  if (fault)
384  correctFault();
385 
386  EquatorialCoordsRNP.np[0].value = targetRA;
387  EquatorialCoordsRNP.np[1].value = targetDEC;
388 
390  IDSetNumber(&EquatorialCoordsRNP, nullptr);
391 }
392 
394 {
395  switch (ConnectSP.sp[0].s)
396  {
397  case ISS_ON:
398 
399  /* Magellan I only has 1200 buad, 8 data bits, 0 parity and 1 stop bit */
400  if (tty_connect(PortTP.tp[0].text, 1200, 8, 0, 1, &fd) != TTY_OK)
401  {
402  ConnectS[0].s = ISS_OFF;
403  ConnectS[1].s = ISS_ON;
404  IDSetSwitch(
405  &ConnectSP,
406  "Error connecting to port %s. Make sure you have BOTH write and read permission to your port.\n",
407  PortTP.tp[0].text);
408  return;
409  }
411  {
412  ConnectS[0].s = ISS_OFF;
413  ConnectS[1].s = ISS_ON;
414  IDSetSwitch(&ConnectSP, "Error connecting to Telescope. Telescope is offline.");
415  return;
416  }
417 
418 #ifdef INDI_DEBUG
419  IDLog("Telescope test successful.\n");
420 #endif
421 
422  ConnectSP.s = IPS_OK;
423  IDSetSwitch(&ConnectSP, "Telescope is online. Retrieving basic data...");
424  getBasicData();
425  break;
426 
427  case ISS_OFF:
428  ConnectS[0].s = ISS_OFF;
429  ConnectS[1].s = ISS_ON;
430  ConnectSP.s = IPS_IDLE;
431  IDSetSwitch(&ConnectSP, "Telescope is offline.");
432  IDLog("Telescope is offline.");
434  break;
435  }
436 }
bool simulation
Definition: magellan1.h:66
void connectTelescope()
Definition: magellan1.cpp:393
int currentSiteNum
Definition: magellan1.h:59
char thisDevice[64]
Definition: magellan1.h:67
virtual ~Magellan1()
Definition: magellan1.cpp:123
virtual void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Definition: magellan1.cpp:176
virtual void ISGetProperties(const char *dev)
Definition: magellan1.cpp:132
bool fault
Definition: magellan1.h:65
double lastDEC
Definition: magellan1.h:64
double targetDEC
Definition: magellan1.h:70
int trackingMode
Definition: magellan1.h:60
double lastRA
Definition: magellan1.h:63
bool isTelescopeOn()
Definition: magellan1.cpp:312
int currentSet
Definition: magellan1.h:68
virtual void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Definition: magellan1.cpp:185
int fd
Definition: magellan1.h:55
virtual void ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Definition: magellan1.cpp:154
virtual void ISPoll()
Definition: magellan1.cpp:335
virtual void getBasicData()
Definition: magellan1.cpp:360
int timeFormat
Definition: magellan1.h:58
void correctFault()
Definition: magellan1.cpp:306
void handleError(ISwitchVectorProperty *svp, int err, const char *msg)
Definition: magellan1.cpp:210
double targetRA
Definition: magellan1.h:70
virtual void ISSnoopDevice(XMLEle *root)
Definition: magellan1.cpp:149
int lastSet
Definition: magellan1.h:69
void setCurrentDeviceName(const char *devName)
Definition: magellan1.cpp:127
#define POLLMS
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition: eventloop.c:582
void ISPoll(void *)
Definition: fli_wheel.c:393
const char * mydev
Definition: ieq45.cpp:41
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition: indiapi.h:500
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
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
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
@ TTY_OK
Definition: indicom.h:150
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition: indidevapi.c:56
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
void IDMessage(const char *dev, const char *fmt,...)
Definition: indidriver.c:960
void IDDefNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1104
void IDDefText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1081
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
void IDDefSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1127
int fd
Definition: intelliscope.c:43
int getCalendarDate(int fd, char *date)
#define currentDEC
Definition: magellan1.cpp:41
ISwitchVectorProperty ConnectSP
Definition: magellan1.cpp:56
INumber EquatorialCoordsRN[]
Definition: magellan1.cpp:77
#define BASIC_GROUP
Definition: magellan1.cpp:34
#define currentRA
Definition: magellan1.cpp:40
INumberVectorProperty EquatorialCoordsRNP
Definition: magellan1.cpp:80
ITextVectorProperty PortTP
Definition: magellan1.cpp:65
#define COMM_GROUP
Definition: magellan1.cpp:33
char * me
Definition: indidriver.c:50
#define getMAGELLANRA(fd, x)
#define getMAGELLANDEC(fd, x)
int check_magellan_connection(int fd)
@ MAGELLAN_24
@ MAGELLAN_TRACK_DEFAULT
One number descriptor.
One switch descriptor.
One text descriptor.
Number vector property descriptor.
Definition: indiapi.h:319
Switch vector property descriptor.
Definition: indiapi.h:367
char name[MAXINDINAME]
Definition: indiapi.h:371
Text vector property descriptor.
Definition: indiapi.h:246
char name[MAXINDINAME]
Definition: indiapi.h:250