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