1 #if 0
2 IEQ45 Basic Driver
3 Copyright (C) 2011 Nacho Mas (mas.ignacio@gmail.com). Only litle changes
4 from lx200basic made it by Jasem Mutlaq (mutlaqja@ikarustech.com)
5
6 This library is free software;
7 you can redistribute it and / or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation;
10 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;
15 without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library;
21 if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA
23
24 #endif
25
26 #include "ieq45.h"
27
28 #include "config.h"
29 #include "ieq45driver.h"
30 #include "indicom.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 #include <unistd.h>
36
37
38 #include <memory>
39
40 const int POLLMS_OVERRIDE = 100; // Period of update, 1 second.
41 const char *mydev = "IEQ45"; // Name of our device.
42
43 const char *BASIC_GROUP = "Main Control"; // Main Group
44 const char *OPTIONS_GROUP = "Options"; // Options Group
45
46 /* Handy Macros */
47 #define currentRA EquatorialCoordsRN[0].value
48 #define currentDEC EquatorialCoordsRN[1].value
49
50 static void ISPoll(void *);
51 static void retry_connection(void *);
52
53 static class Loader
54 {
55 std::unique_ptr<IEQ45Basic> telescope;
56 public:
Loader()57 Loader()
58 {
59 telescope.reset(new IEQ45Basic());
60 IEAddTimer(POLLMS_OVERRIDE, ISPoll, nullptr);
61 }
62 } loader;
63
64 /**************************************************************************************
65 **
66 ***************************************************************************************/
ISPoll(void * p)67 void ISPoll(void *p)
68 {
69 INDI_UNUSED(p);
70
71 telescope->ISPoll();
72 IEAddTimer(POLLMS_OVERRIDE, ISPoll, nullptr);
73 }
74
75 /**************************************************************************************
76 ** IEQ45 Basic constructor
77 ***************************************************************************************/
IEQ45Basic()78 IEQ45Basic::IEQ45Basic()
79 {
80 init_properties();
81
82 lastSet = -1;
83 fd = -1;
84 simulation = false;
85 lastRA = 0;
86 lastDEC = 0;
87 currentSet = 0;
88
89 IDLog("Initializing from IEQ45 device...\n");
90 IDLog("Driver Version: 0.1 (2011-11-07)\n");
91
92 enable_simulation(false);
93 }
94
95 /**************************************************************************************
96 **
97 ***************************************************************************************/
~IEQ45Basic()98 IEQ45Basic::~IEQ45Basic()
99 {
100 }
101
102 /**************************************************************************************
103 ** Initialize all properties & set default values.
104 ***************************************************************************************/
init_properties()105 void IEQ45Basic::init_properties()
106 {
107 // Connection#include <stdio.h>
108 #include <string.h>
109 IUFillSwitch(&ConnectS[0], "CONNECT", "Connect", ISS_OFF);
110 IUFillSwitch(&ConnectS[1], "DISCONNECT", "Disconnect", ISS_ON);
111 IUFillSwitchVector(&ConnectSP, ConnectS, NARRAY(ConnectS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW,
112 ISR_1OFMANY, 60, IPS_IDLE);
113
114 // Coord Set
115 IUFillSwitch(&OnCoordSetS[0], "SLEW", "Slew", ISS_ON);
116 IUFillSwitch(&OnCoordSetS[1], "SYNC", "Sync", ISS_OFF);
117 IUFillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP,
118 IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
119
120 //Track MODE
121 IUFillSwitch(&TrackModeS[0], "SIDEREAL", "Sidereal", ISS_ON);
122 IUFillSwitch(&TrackModeS[1], "LUNAR", "Lunar", ISS_OFF);
123 IUFillSwitch(&TrackModeS[2], "SOLAR", "Solar", ISS_OFF);
124 IUFillSwitch(&TrackModeS[3], "ZERO", "Stop", ISS_OFF);
125 IUFillSwitchVector(&TrackModeSP, TrackModeS, NARRAY(TrackModeS), mydev, "TRACK_MODE", "Track Mode", BASIC_GROUP,
126 IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
127
128 // Abort
129 IUFillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
130 IUFillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort Slew/Track",
131 BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
132
133 // Port
134 IUFillText(&PortT[0], "PORT", "Port", "/dev/ttyS0");
135 IUFillTextVector(&PortTP, PortT, NARRAY(PortT), mydev, "DEVICE_PORT", "Ports", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
136
137 // Equatorial Coords
138 IUFillNumber(&EquatorialCoordsRN[0], "RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0.);
139 IUFillNumber(&EquatorialCoordsRN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
140 IUFillNumberVector(&EquatorialCoordsRNP, EquatorialCoordsRN, NARRAY(EquatorialCoordsRN), mydev,
141 "EQUATORIAL_EOD_COORD", "Equatorial JNow", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
142 }
143
144 /**************************************************************************************
145 ** Define IEQ45 Basic properties to clients.
146 ***************************************************************************************/
ISGetProperties(const char * dev)147 void IEQ45Basic::ISGetProperties(const char *dev)
148 {
149 if (dev != nullptr && strcmp(mydev, dev))
150 return;
151
152 // Main Control
153 IDDefSwitch(&ConnectSP, nullptr);
154 IDDefText(&PortTP, nullptr);
155 IDDefNumber(&EquatorialCoordsRNP, nullptr);
156 IDDefSwitch(&OnCoordSetSP, nullptr);
157 IDDefSwitch(&TrackModeSP, nullptr);
158 IDDefSwitch(&AbortSlewSP, nullptr);
159 }
160
161 /**************************************************************************************
162 ** Process Text properties
163 ***************************************************************************************/
ISNewText(const char * dev,const char * name,char * texts[],char * names[],int n)164 void IEQ45Basic::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
165 {
166 // Ignore if not ours
167 if (strcmp(dev, mydev))
168 return;
169
170 // ===================================
171 // Port Name
172 // ===================================
173 if (!strcmp(name, PortTP.name))
174 {
175 if (IUUpdateText(&PortTP, texts, names, n) < 0)
176 return;
177
178 PortTP.s = IPS_OK;
179 IDSetText(&PortTP, nullptr);
180 return;
181 }
182
183 if (is_connected() == false)
184 {
185 IDMessage(mydev, "IEQ45 is offline. Please connect before issuing any commands.");
186 reset_all_properties();
187 return;
188 }
189 }
190
191 /**************************************************************************************
192 **
193 ***************************************************************************************/
ISNewNumber(const char * dev,const char * name,double values[],char * names[],int n)194 void IEQ45Basic::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
195 {
196 // Ignore if not ours
197 if (strcmp(dev, mydev))
198 return;
199
200 if (is_connected() == false)
201 {
202 IDMessage(mydev, "IEQ45 is offline. Please connect before issuing any commands.");
203 reset_all_properties();
204 return;
205 }
206
207 // ===================================
208 // Equatorial Coords
209 // ===================================
210 if (!strcmp(name, EquatorialCoordsRNP.name))
211 {
212 int i = 0, nset = 0, error_code = 0;
213 double newRA = 0, newDEC = 0;
214
215 for (nset = i = 0; i < n; i++)
216 {
217 INumber *eqp = IUFindNumber(&EquatorialCoordsRNP, names[i]);
218 if (eqp == &EquatorialCoordsRN[0])
219 {
220 newRA = values[i];
221 nset += newRA >= 0 && newRA <= 24.0;
222 }
223 else if (eqp == &EquatorialCoordsRN[1])
224 {
225 newDEC = values[i];
226 nset += newDEC >= -90.0 && newDEC <= 90.0;
227 }
228 }
229
230 if (nset == 2)
231 {
232 char RAStr[32], DecStr[32];
233
234 fs_sexa(RAStr, newRA, 2, 3600);
235 fs_sexa(DecStr, newDEC, 2, 3600);
236
237 #ifdef INDI_DEBUG
238 IDLog("We received JNow RA %g - DEC %g\n", newRA, newDEC);
239 IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
240 #endif
241
242 if (!simulation &&
243 ((error_code = setObjectRA(fd, newRA)) < 0 || (error_code = setObjectDEC(fd, newDEC)) < 0))
244 {
245 handle_error(&EquatorialCoordsRNP, error_code, "Setting RA/DEC");
246 return;
247 }
248
249 targetRA = newRA;
250 targetDEC = newDEC;
251
252 if (process_coords() == false)
253 {
254 EquatorialCoordsRNP.s = IPS_ALERT;
255 IDSetNumber(&EquatorialCoordsRNP, nullptr);
256 }
257 } // end nset
258 else
259 {
260 EquatorialCoordsRNP.s = IPS_ALERT;
261 IDSetNumber(&EquatorialCoordsRNP, "RA or Dec missing or invalid");
262 }
263
264 return;
265 } /* end EquatorialCoordsWNP */
266 }
267
268 /**************************************************************************************
269 **
270 ***************************************************************************************/
ISNewSwitch(const char * dev,const char * name,ISState * states,char * names[],int n)271 void IEQ45Basic::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
272 {
273 // ignore if not ours //
274 if (strcmp(mydev, dev))
275 return;
276
277 // ===================================
278 // Connect Switch
279 // ===================================
280 if (!strcmp(name, ConnectSP.name))
281 {
282 if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
283 return;
284
285 connect_telescope();
286 return;
287 }
288
289 if (is_connected() == false)
290 {
291 IDMessage(mydev, "IEQ45 is offline. Please connect before issuing any commands.");
292 reset_all_properties();
293 return;
294 }
295
296 // ===================================
297 // Coordinate Set
298 // ===================================
299 if (!strcmp(name, OnCoordSetSP.name))
300 {
301 if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
302 return;
303
304 currentSet = get_switch_index(&OnCoordSetSP);
305 OnCoordSetSP.s = IPS_OK;
306 IDSetSwitch(&OnCoordSetSP, nullptr);
307 }
308
309 // ===================================
310 // Track Mode Set
311 // ===================================
312 if (!strcmp(name, TrackModeSP.name))
313 {
314 if (IUUpdateSwitch(&TrackModeSP, states, names, n) < 0)
315 return;
316
317 int trackMode = get_switch_index(&TrackModeSP);
318 selectTrackingMode(fd, trackMode);
319 TrackModeSP.s = IPS_OK;
320 IDSetSwitch(&TrackModeSP, nullptr);
321 }
322
323 // ===================================
324 // Abort slew
325 // ===================================
326 if (!strcmp(name, AbortSlewSP.name))
327 {
328 IUResetSwitch(&AbortSlewSP);
329 abortSlew(fd);
330
331 if (EquatorialCoordsRNP.s == IPS_BUSY)
332 {
333 AbortSlewSP.s = IPS_OK;
334 EquatorialCoordsRNP.s = IPS_IDLE;
335 IDSetSwitch(&AbortSlewSP, "Slew aborted.");
336 IDSetNumber(&EquatorialCoordsRNP, nullptr);
337 }
338
339 return;
340 }
341 }
342
343 /**************************************************************************************
344 ** Retry connecting to the telescope on error. Give up if there is no hope.
345 ***************************************************************************************/
handle_error(INumberVectorProperty * nvp,int err,const char * msg)346 void IEQ45Basic::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
347 {
348 nvp->s = IPS_ALERT;
349
350 /* First check to see if the telescope is connected */
351 if (check_IEQ45_connection(fd))
352 {
353 /* The telescope is off locally */
354 ConnectS[0].s = ISS_OFF;
355 ConnectS[1].s = ISS_ON;
356 ConnectSP.s = IPS_BUSY;
357 IDSetSwitch(&ConnectSP, "Telescope is not responding to commands, will retry in 10 seconds.");
358
359 IDSetNumber(nvp, nullptr);
360 IEAddTimer(10000, retry_connection, &fd);
361 return;
362 }
363
364 /* If the error is a time out, then the device doesn't support this property */
365 if (err == -2)
366 {
367 nvp->s = IPS_ALERT;
368 IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
369 }
370 else
371 /* Changing property failed, user should retry. */
372 IDSetNumber(nvp, "%s failed.", msg);
373
374 fault = true;
375 }
376
377 /**************************************************************************************
378 ** Set all properties to idle and reset most switches to clean state.
379 ***************************************************************************************/
reset_all_properties()380 void IEQ45Basic::reset_all_properties()
381 {
382 ConnectSP.s = IPS_IDLE;
383 OnCoordSetSP.s = IPS_IDLE;
384 TrackModeSP.s = IPS_IDLE;
385 AbortSlewSP.s = IPS_IDLE;
386 PortTP.s = IPS_IDLE;
387 EquatorialCoordsRNP.s = IPS_IDLE;
388
389 IUResetSwitch(&OnCoordSetSP);
390 IUResetSwitch(&TrackModeSP);
391 IUResetSwitch(&AbortSlewSP);
392
393 OnCoordSetS[0].s = ISS_ON;
394 TrackModeS[0].s = ISS_ON;
395 ConnectS[0].s = ISS_OFF;
396 ConnectS[1].s = ISS_ON;
397
398 IDSetSwitch(&ConnectSP, nullptr);
399 IDSetSwitch(&OnCoordSetSP, nullptr);
400 IDSetSwitch(&TrackModeSP, nullptr);
401 IDSetSwitch(&AbortSlewSP, nullptr);
402 IDSetText(&PortTP, nullptr);
403 IDSetNumber(&EquatorialCoordsRNP, nullptr);
404 }
405
406 /**************************************************************************************
407 **
408 ***************************************************************************************/
correct_fault()409 void IEQ45Basic::correct_fault()
410 {
411 fault = false;
412 IDMessage(mydev, "Telescope is online.");
413 }
414
415 /**************************************************************************************
416 **
417 ***************************************************************************************/
is_connected()418 bool IEQ45Basic::is_connected()
419 {
420 if (simulation)
421 return true;
422
423 return (ConnectSP.sp[0].s == ISS_ON);
424 }
425
426 /**************************************************************************************
427 **
428 ***************************************************************************************/
retry_connection(void * p)429 static void retry_connection(void *p)
430 {
431 int fd = *((int *)p);
432
433 if (check_IEQ45_connection(fd))
434 telescope->connection_lost();
435 else
436 telescope->connection_resumed();
437 }
438
439 /**************************************************************************************
440 **
441 ***************************************************************************************/
ISPoll()442 void IEQ45Basic::ISPoll()
443 {
444 if (is_connected() == false || simulation)
445 return;
446
447 double dx, dy;
448 int error_code = 0;
449
450 switch (EquatorialCoordsRNP.s)
451 {
452 case IPS_IDLE:
453 getIEQ45RA(fd, ¤tRA);
454 getIEQ45DEC(fd, ¤tDEC);
455 if (fabs(currentRA - lastRA) > 0.01 || fabs(currentDEC - lastDEC) > 0.01)
456 {
457 lastRA = currentRA;
458 lastDEC = currentDEC;
459 IDSetNumber(&EquatorialCoordsRNP, nullptr);
460 IDLog("IDLE update coord\n");
461 }
462 break;
463
464 case IPS_BUSY:
465 getIEQ45RA(fd, ¤tRA);
466 getIEQ45DEC(fd, ¤tDEC);
467 dx = targetRA - currentRA;
468 dy = targetDEC - currentDEC;
469
470 // Wait until acknowledged or within threshold
471 if (fabs(dx) <= (3 / (900.0)) && fabs(dy) <= (3 / 60.0))
472 {
473 lastRA = currentRA;
474 lastDEC = currentDEC;
475 IUResetSwitch(&OnCoordSetSP);
476 OnCoordSetSP.s = IPS_OK;
477 EquatorialCoordsRNP.s = IPS_OK;
478 IDSetNumber(&EquatorialCoordsRNP, nullptr);
479
480 switch (currentSet)
481 {
482 case IEQ45_SLEW:
483 OnCoordSetSP.sp[IEQ45_SLEW].s = ISS_ON;
484 IDSetSwitch(&OnCoordSetSP, "Slew is complete.");
485 break;
486
487 case IEQ45_SYNC:
488 break;
489 }
490 }
491 else
492 IDSetNumber(&EquatorialCoordsRNP, nullptr);
493 break;
494
495 case IPS_OK:
496
497 if ((error_code = getIEQ45RA(fd, ¤tRA)) < 0 || (error_code = getIEQ45DEC(fd, ¤tDEC)) < 0)
498 {
499 handle_error(&EquatorialCoordsRNP, error_code, "Getting RA/DEC");
500 return;
501 }
502
503 if (fault == true)
504 correct_fault();
505
506 if ((currentRA != lastRA) || (currentDEC != lastDEC))
507 {
508 lastRA = currentRA;
509 lastDEC = currentDEC;
510 //IDLog("IPS_OK update coords %g %g\n",currentRA,currentDEC);
511 IDSetNumber(&EquatorialCoordsRNP, nullptr);
512 }
513 break;
514
515 case IPS_ALERT:
516 break;
517 }
518 }
519
520 /**************************************************************************************
521 **
522 ***************************************************************************************/
process_coords()523 bool IEQ45Basic::process_coords()
524 {
525 int error_code;
526 char syncString[256];
527 char RAStr[32], DecStr[32];
528 double dx, dy;
529
530 switch (currentSet)
531 {
532 // Slew
533 case IEQ45_SLEW:
534 lastSet = IEQ45_SLEW;
535 if (EquatorialCoordsRNP.s == IPS_BUSY)
536 {
537 IDLog("Aborting Slew\n");
538 abortSlew(fd);
539
540 // sleep for 100 mseconds
541 usleep(100000);
542 }
543
544 if (!simulation && (error_code = Slew(fd)))
545 {
546 slew_error(error_code);
547 return false;
548 }
549
550 EquatorialCoordsRNP.s = IPS_BUSY;
551 fs_sexa(RAStr, targetRA, 2, 3600);
552 fs_sexa(DecStr, targetDEC, 2, 3600);
553 IDSetNumber(&EquatorialCoordsRNP, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
554 IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
555 break;
556
557 // Sync
558 case IEQ45_SYNC:
559 lastSet = IEQ45_SYNC;
560 EquatorialCoordsRNP.s = IPS_IDLE;
561
562 if (!simulation && (error_code = Sync(fd, syncString) < 0))
563 {
564 IDSetNumber(&EquatorialCoordsRNP, "Synchronization failed.");
565 return false;
566 }
567
568 if (simulation)
569 {
570 EquatorialCoordsRN[0].value = EquatorialCoordsRN[0].value;
571 EquatorialCoordsRN[1].value = EquatorialCoordsRN[1].value;
572 }
573
574 EquatorialCoordsRNP.s = IPS_OK;
575 IDLog("Synchronization successful %s\n", syncString);
576 IDSetNumber(&EquatorialCoordsRNP, "Synchronization successful.");
577 break;
578 }
579
580 return true;
581 }
582
583 /**************************************************************************************
584 **
585 ***************************************************************************************/
get_switch_index(ISwitchVectorProperty * sp)586 int IEQ45Basic::get_switch_index(ISwitchVectorProperty *sp)
587 {
588 for (int i = 0; i < sp->nsp; i++)
589 if (sp->sp[i].s == ISS_ON)
590 return i;
591
592 return -1;
593 }
594
595 /**************************************************************************************
596 **
597 ***************************************************************************************/
connect_telescope()598 void IEQ45Basic::connect_telescope()
599 {
600 switch (ConnectSP.sp[0].s)
601 {
602 case ISS_ON:
603
604 if (simulation)
605 {
606 ConnectSP.s = IPS_OK;
607 IDSetSwitch(&ConnectSP, "Simulated telescope is online.");
608 return;
609 }
610
611 if (tty_connect(PortT[0].text, 9600, 8, 0, 1, &fd) != TTY_OK)
612 {
613 ConnectS[0].s = ISS_OFF;
614 ConnectS[1].s = ISS_ON;
615 IDSetSwitch(
616 &ConnectSP,
617 "Error connecting to port %s. Make sure you have BOTH read and write permission to the port.",
618 PortT[0].text);
619 return;
620 }
621
622 if (check_IEQ45_connection(fd))
623 {
624 ConnectS[0].s = ISS_OFF;
625 ConnectS[1].s = ISS_ON;
626 IDSetSwitch(&ConnectSP, "Error connecting to Telescope. Telescope is offline.");
627 return;
628 }
629
630 ConnectSP.s = IPS_OK;
631 IDSetSwitch(&ConnectSP, "Telescope is online. Retrieving basic data...");
632 get_initial_data();
633 break;
634
635 case ISS_OFF:
636 ConnectS[0].s = ISS_OFF;
637 ConnectS[1].s = ISS_ON;
638 ConnectSP.s = IPS_IDLE;
639 if (simulation)
640 {
641 IDSetSwitch(&ConnectSP, "Simulated Telescope is offline.");
642 return;
643 }
644 IDSetSwitch(&ConnectSP, "Telescope is offline.");
645 IDLog("Telescope is offline.");
646
647 tty_disconnect(fd);
648 break;
649 }
650 }
651
652 /**************************************************************************************
653 **
654 ***************************************************************************************/
get_initial_data()655 void IEQ45Basic::get_initial_data()
656 {
657 // Make sure short
658 checkIEQ45Format(fd);
659
660 // Get current RA/DEC
661 getIEQ45RA(fd, ¤tRA);
662 getIEQ45DEC(fd, ¤tDEC);
663
664 IDSetNumber(&EquatorialCoordsRNP, nullptr);
665 }
666
667 /**************************************************************************************
668 **
669 ***************************************************************************************/
slew_error(int slewCode)670 void IEQ45Basic::slew_error(int slewCode)
671 {
672 OnCoordSetSP.s = IPS_IDLE;
673 IDLog("Aborting Slew\n");
674 abortSlew(fd);
675 if (slewCode == 1)
676 IDSetSwitch(&OnCoordSetSP, "Object below horizon.");
677 else if (slewCode == 2)
678 IDSetSwitch(&OnCoordSetSP, "Object below the minimum elevation limit.");
679 else
680 IDSetSwitch(&OnCoordSetSP, "Slew failed.");
681 }
682
683 /**************************************************************************************
684 **
685 ***************************************************************************************/
enable_simulation(bool enable)686 void IEQ45Basic::enable_simulation(bool enable)
687 {
688 simulation = enable;
689
690 if (simulation)
691 IDLog("Warning: Simulation is activated.\n");
692 else
693 IDLog("Simulation is disabled.\n");
694 }
695
696 /**************************************************************************************
697 **
698 ***************************************************************************************/
connection_lost()699 void IEQ45Basic::connection_lost()
700 {
701 ConnectSP.s = IPS_IDLE;
702 IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
703 return;
704 }
705
706 /**************************************************************************************
707 **
708 ***************************************************************************************/
connection_resumed()709 void IEQ45Basic::connection_resumed()
710 {
711 ConnectS[0].s = ISS_ON;
712 ConnectS[1].s = ISS_OFF;
713 ConnectSP.s = IPS_OK;
714
715 IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
716 }
717