Instrument Neutral Distributed Interface INDI 2.2.5
gemini.cpp
Go to the documentation of this file.
1/*
2 Optec Gemini Focuser Rotator INDI driver
3 Copyright (C) 2017 Jasem Mutlaq ([email protected])
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20#include "gemini.h"
21
22#include "indicom.h"
24
25#include <cmath>
26#include <memory>
27#include <cstring>
28#include <termios.h>
29#include <unistd.h>
30
31#define GEMINI_MAX_RETRIES 1
32#define GEMINI_TIMEOUT 3
33#define GEMINI_MAXBUF 16
34#define GEMINI_TEMPERATURE_FREQ 20 /* Update every 20 POLLMS cycles. For POLLMS 500ms = 10 seconds freq */
35#define GEMINI_POSITION_THRESHOLD 5 /* Only send position updates to client if the diff exceeds 5 steps */
36
37#define FOCUS_SETTINGS_TAB "Settings"
38#define STATUS_TAB "Status"
39#define ROTATOR_TAB "Rotator"
40#define HUB_TAB "Hub"
41
42static std::unique_ptr<Gemini> geminiFR(new Gemini());
43
44/************************************************************************************
45 *
46* ***********************************************************************************/
48{
49 focusMoveRequest = 0;
50 focuserSimPosition = 0;
51
52 // Can move in Absolute & Relative motions and can AbortFocuser motion.
54
55 // Rotator capabilities
57
58 isFocuserAbsolute = true;
59 isFocuserHoming = false;
60
61 focuserSimStatus[STATUS_MOVING] = ISS_OFF;
62 focuserSimStatus[STATUS_HOMING] = ISS_OFF;
63 focuserSimStatus[STATUS_HOMED] = ISS_OFF;
64 focuserSimStatus[STATUS_FFDETECT] = ISS_OFF;
65 focuserSimStatus[STATUS_TMPPROBE] = ISS_ON;
66 focuserSimStatus[STATUS_REMOTEIO] = ISS_ON;
67 focuserSimStatus[STATUS_HNDCTRL] = ISS_ON;
68 focuserSimStatus[STATUS_REVERSE] = ISS_OFF;
69
70 DBG_FOCUS = INDI::Logger::getInstance().addDebugLevel("Verbose", "Verbose");
71}
72
73/************************************************************************************
74 *
75* ***********************************************************************************/
79
80/************************************************************************************
81 *
82* ***********************************************************************************/
84{
86
88 // Focuser Properties
90
91 TemperatureNP[0].fill("TEMPERATURE", "Celsius", "%6.2f", -50, 70., 0., 0.);
92 TemperatureNP.fill(getDeviceName(), "FOCUS_TEMPERATURE", "Temperature",
94
95 // Enable/Disable temperature compensation
96 TemperatureCompensateSP[INDI_ENABLED].fill("Enable", "", ISS_OFF);
97 TemperatureCompensateSP[INDI_DISABLED].fill("Disable", "", ISS_ON);
98 TemperatureCompensateSP.fill(getDeviceName(), "T. Compensation", "",
100
101 // Enable/Disable temperature compensation on start
102 TemperatureCompensateOnStartSP[INDI_ENABLED].fill("Enable", "", ISS_OFF);
103 TemperatureCompensateOnStartSP[INDI_DISABLED].fill("Disable", "", ISS_ON);
104 TemperatureCompensateOnStartSP.fill(getDeviceName(),
105 "T. Compensation @Start", "", FOCUS_SETTINGS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
106
107 // Temperature Coefficient
108 TemperatureCoeffNP[A].fill("A", "", "%.f", -9999, 9999, 100., 0.);
109 TemperatureCoeffNP[B].fill("B", "", "%.f", -9999, 9999, 100., 0.);
110 TemperatureCoeffNP[C].fill("C", "", "%.f", -9999, 9999, 100., 0.);
111 TemperatureCoeffNP[D].fill("D", "", "%.f", -9999, 9999, 100., 0.);
112 TemperatureCoeffNP[E].fill("E", "", "%.f", -9999, 9999, 100., 0.);
113 TemperatureCoeffNP.fill(getDeviceName(), "T. Coeff", "", FOCUS_SETTINGS_TAB,
114 IP_RW, 0, IPS_IDLE);
115
116 // Enable/Disable Home on Start
117 FocuserHomeOnStartSP[INDI_ENABLED].fill("Enable", "", ISS_OFF);
118 FocuserHomeOnStartSP[INDI_DISABLED].fill("Disable", "", ISS_ON);
119 FocuserHomeOnStartSP.fill(getDeviceName(), "FOCUSER_HOME_ON_START", "Home on Start",
121
122 // Enable/Disable temperature Mode
123 TemperatureCompensateModeSP[A].fill("A", "", ISS_OFF);
124 TemperatureCompensateModeSP[B].fill("B", "", ISS_OFF);
125 TemperatureCompensateModeSP[C].fill( "C", "", ISS_OFF);
126 TemperatureCompensateModeSP[D].fill( "D", "", ISS_OFF);
127 TemperatureCompensateModeSP[E].fill( "E", "", ISS_OFF);
128 TemperatureCompensateModeSP.fill(getDeviceName(), "Compensate Mode",
130
131 // // Enable/Disable backlash
132 // IUFillSwitch(&FocusBacklashS[0], "Enable", "", ISS_OFF);
133 // IUFillSwitch(&FocusBacklashS[1], "Disable", "", ISS_ON);
134 // IUFillSwitchVector(&FocusBacklashSP, FocusBacklashS, 2, getDeviceName(), "FOCUSER_BACKLASH_COMPENSATION", "Backlash Compensation",
135 // FOCUS_SETTINGS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
136
137 // // Backlash Value
138 // IUFillNumber(&FocusBacklashN[0], "Value", "", "%.f", 0, 99, 5., 0.);
139 // IUFillNumberVector(&FocusBacklashNP, FocusBacklashN, 1, getDeviceName(), "FOCUSER_BACKLASH", "Backlash", FOCUS_SETTINGS_TAB, IP_RW, 0,
140 // IPS_IDLE);
141
142 // Go to home/center
143 FocuserGotoSP[GOTO_CENTER].fill("Center", "", ISS_OFF);
144 FocuserGotoSP[GOTO_HOME].fill("Home", "", ISS_OFF);
145 FocuserGotoSP.fill(getDeviceName(), "FOCUSER_GOTO", "Goto", MAIN_CONTROL_TAB, IP_RW,
146 ISR_1OFMANY, 0,
147 IPS_IDLE);
148
149 // Focus Status indicators
150 FocuserStatusLP[STATUS_MOVING].fill("Is Moving", "", IPS_IDLE);
151 FocuserStatusLP[STATUS_HOMING].fill("Is Homing", "", IPS_IDLE);
152 FocuserStatusLP[STATUS_HOMED].fill("Is Homed", "", IPS_IDLE);
153 FocuserStatusLP[STATUS_FFDETECT].fill("FF Detect", "", IPS_IDLE);
154 FocuserStatusLP[STATUS_TMPPROBE].fill("Tmp Probe", "", IPS_IDLE);
155 FocuserStatusLP[STATUS_REMOTEIO].fill("Remote IO", "", IPS_IDLE);
156 FocuserStatusLP[STATUS_HNDCTRL].fill("Hnd Ctrl", "", IPS_IDLE);
157 FocuserStatusLP[STATUS_REVERSE].fill("Reverse", "", IPS_IDLE);
158 FocuserStatusLP.fill(getDeviceName(), "FOCUSER_STATUS", "Focuser", STATUS_TAB, IPS_IDLE);
159
161 // Rotator Properties
163
164 // Enable/Disable Home on Start
165 RotatorHomeOnStartSP[INDI_ENABLED].fill("Enable", "", ISS_OFF);
166 RotatorHomeOnStartSP[INDI_DISABLED].fill("Disable", "", ISS_ON);
167 RotatorHomeOnStartSP.fill(getDeviceName(), "ROTATOR_HOME_ON_START", "Home on Start",
169
170 // Rotator Status indicators
171 RotatorStatusLP[STATUS_MOVING].fill("Is Moving", "", IPS_IDLE);
172 RotatorStatusLP[STATUS_HOMING].fill("Is Homing", "", IPS_IDLE);
173 RotatorStatusLP[STATUS_HOMED].fill("Is Homed", "", IPS_IDLE);
174 RotatorStatusLP[STATUS_FFDETECT].fill("FF Detect", "", IPS_IDLE);
175 RotatorStatusLP[STATUS_TMPPROBE].fill("Tmp Probe", "", IPS_IDLE);
176 RotatorStatusLP[STATUS_REMOTEIO].fill("Remote IO", "", IPS_IDLE);
177 RotatorStatusLP[STATUS_HNDCTRL].fill("Hnd Ctrl", "", IPS_IDLE);
178 RotatorStatusLP[STATUS_REVERSE].fill("Reverse", "", IPS_IDLE);
179 RotatorStatusLP.fill(getDeviceName(), "ROTATOR_STATUS", "Rotator", STATUS_TAB, IPS_IDLE);
180
182
183 // Rotator Ticks
184 RotatorAbsPosNP[0].fill("ROTATOR_ABSOLUTE_POSITION", "Ticks", "%.f", 0., 0., 0., 0.);
185 RotatorAbsPosNP.fill(getDeviceName(), "ABS_ROTATOR_POSITION", "Goto", ROTATOR_TAB, IP_RW,
186 0, IPS_IDLE );
187#if 0
188
189
190 // Rotator Degree
191 IUFillNumber(&RotatorAbsAngleN[0], "ANGLE", "Degrees", "%.2f", 0, 360., 10., 0.);
192 IUFillNumberVector(&RotatorAbsAngleNP, RotatorAbsAngleN, 1, getDeviceName(), "ABS_ROTATOR_ANGLE", "Angle", ROTATOR_TAB,
193 IP_RW, 0, IPS_IDLE );
194
195 // Abort Rotator
196 IUFillSwitch(&AbortRotatorS[0], "ABORT", "Abort", ISS_OFF);
197 IUFillSwitchVector(&AbortRotatorSP, AbortRotatorS, 1, getDeviceName(), "ROTATOR_ABORT_MOTION", "Abort Motion", ROTATOR_TAB,
199
200 // Rotator Go to home/center
201 IUFillSwitch(&RotatorGotoS[GOTO_CENTER], "Center", "", ISS_OFF);
202 IUFillSwitch(&RotatorGotoS[GOTO_HOME], "Home", "", ISS_OFF);
203 IUFillSwitchVector(&RotatorGotoSP, RotatorGotoS, 2, getDeviceName(), "ROTATOR_GOTO", "Goto", ROTATOR_TAB, IP_RW,
204 ISR_1OFMANY, 0,
205 IPS_IDLE);
206#endif
207
209 // Hub Properties
211
212 // Focus name configure in the HUB
213 HFocusNameTP[DEVICE_FOCUSER].fill("FocusName", "Focuser name", "");
214 HFocusNameTP[DEVICE_ROTATOR].fill("RotatorName", "Rotator name", "");
215 HFocusNameTP.fill(getDeviceName(), "HUBNAMES", "HUB", HUB_TAB, IP_RW, 0,
216 IPS_IDLE);
217
218 // Led intensity value
219 LedNP[0].fill("Intensity", "", "%.f", 0, 100, 5., 0.);
220 LedNP.fill(getDeviceName(), "Led", "", HUB_TAB, IP_RW, 0, IPS_IDLE);
221
222 // Reset to Factory setting
223 ResetSP[0].fill("Factory", "", ISS_OFF);
224 ResetSP.fill(getDeviceName(), "Reset", "", HUB_TAB, IP_RW, ISR_ATMOST1, 0,
225 IPS_IDLE);
226
228
230
232
233 return true;
234}
235
236/************************************************************************************
237 *
238* ***********************************************************************************/
240{
242
243 if (isConnected())
244 {
245 // Focuser Properties
246 defineProperty(TemperatureNP);
247 defineProperty(TemperatureCoeffNP);
248 defineProperty(TemperatureCompensateModeSP);
249 defineProperty(TemperatureCompensateSP);
250 defineProperty(TemperatureCompensateOnStartSP);
251 // defineProperty(&FocusBacklashSP);
252 // defineProperty(&FocusBacklashNP);
253 defineProperty(FocuserHomeOnStartSP);
254 defineProperty(FocuserGotoSP);
255 defineProperty(FocuserStatusLP);
256
257 // Rotator Properties
259 /*
260
261 defineProperty(&RotatorAbsAngleNP);
262 defineProperty(&AbortRotatorSP);
263 defineProperty(&RotatorGotoSP);
264 defineProperty(&ReverseRotatorSP);
265 */
266 defineProperty(RotatorAbsPosNP);
267 defineProperty(RotatorHomeOnStartSP);
268 defineProperty(RotatorStatusLP);
269
270 // Hub Properties
271 defineProperty(HFocusNameTP);
272 defineProperty(ResetSP);
273 defineProperty(LedNP);
274
275 if (getFocusConfig() && getRotatorConfig())
276 LOG_INFO("Gemini parameters updated, rotating focuser ready for use.");
277 else
278 {
279 LOG_ERROR("Failed to retrieve rotating focuser configuration settings...");
280 return false;
281 }
282 }
283 else
284 {
285 // Focuser Properties
286 deleteProperty(TemperatureNP);
287 deleteProperty(TemperatureCoeffNP);
288 deleteProperty(TemperatureCompensateModeSP);
289 deleteProperty(TemperatureCompensateSP);
290 deleteProperty(TemperatureCompensateOnStartSP);
291 // deleteProperty(FocusBacklashSP.name);
292 // deleteProperty(FocusBacklashNP.name);
293 deleteProperty(FocuserGotoSP);
294 deleteProperty(FocuserHomeOnStartSP);
295 deleteProperty(FocuserStatusLP);
296
297 // Rotator Properties
299 /*
300 deleteProperty(RotatorAbsAngleNP.name);
301 deleteProperty(AbortRotatorSP.name);
302 deleteProperty(RotatorGotoSP.name);
303 deleteProperty(ReverseRotatorSP.name);
304 */
305
306 deleteProperty(RotatorAbsPosNP);
307 deleteProperty(RotatorHomeOnStartSP);
308
309 deleteProperty(RotatorStatusLP);
310
311 // Hub Properties
312 deleteProperty(HFocusNameTP);
313 deleteProperty(LedNP);
314 deleteProperty(ResetSP);
315 }
316
317 return true;
318}
319
320/************************************************************************************
321 *
322* ***********************************************************************************/
324{
325 if (ack())
326 {
327 LOG_INFO("Gemini is online. Getting focus parameters...");
328 return true;
329 }
330
331 LOG_INFO("Error retrieving data from Gemini, please ensure Gemini controller is "
332 "powered and the port is correct.");
333 return false;
334}
335
336/************************************************************************************
337 *
338* ***********************************************************************************/
340{
341 // Has to be overridden by child instance
342 return "Gemini Focusing Rotator";
343}
344
345/************************************************************************************
346 *
347* ***********************************************************************************/
348bool Gemini::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
349{
350 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
351 {
352 // Temperature Compensation
353 if (TemperatureCompensateSP.isNameMatch(name))
354 {
355 int prevIndex = TemperatureCompensateSP.findOnSwitchIndex();
356 TemperatureCompensateSP.update(states, names, n);
357 if (setTemperatureCompensation(TemperatureCompensateSP[INDI_ENABLED].getState() == ISS_ON))
358 {
359 TemperatureCompensateSP.setState(IPS_OK);
360 }
361 else
362 {
363 TemperatureCompensateSP.reset();
364 TemperatureCompensateSP.setState(IPS_ALERT);
365 TemperatureCompensateSP[prevIndex].setState(ISS_ON);
366 }
367
368 TemperatureCompensateSP.apply();
369 return true;
370 }
371
372 // Temperature Compensation on Start
373 if (TemperatureCompensateOnStartSP.isNameMatch(name))
374 {
375 int prevIndex = TemperatureCompensateOnStartSP.findOnSwitchIndex();
376 TemperatureCompensateOnStartSP.update(states, names, n);
377 if (setTemperatureCompensationOnStart(TemperatureCompensateOnStartSP[INDI_ENABLED].getState() == ISS_ON))
378 {
379 TemperatureCompensateOnStartSP.setState(IPS_OK);
380 }
381 else
382 {
383 TemperatureCompensateOnStartSP.reset();
384 TemperatureCompensateOnStartSP.setState(IPS_ALERT);
385 TemperatureCompensateOnStartSP[prevIndex].setState(ISS_ON);
386 }
387
388 TemperatureCompensateOnStartSP.apply();
389 return true;
390 }
391
392 // Temperature Compensation Mode
393 if (TemperatureCompensateModeSP.isNameMatch(name))
394 {
395 int prevIndex = TemperatureCompensateModeSP.findOnSwitchIndex();
396 TemperatureCompensateModeSP.update(states, names, n);
397 char mode = TemperatureCompensateModeSP.findOnSwitchIndex() + 'A';
398 if (setTemperatureCompensationMode(mode))
399 {
400 TemperatureCompensateModeSP.setState(IPS_OK);
401 }
402 else
403 {
404 TemperatureCompensateModeSP.reset();
405 TemperatureCompensateModeSP.setState(IPS_ALERT);
406 TemperatureCompensateModeSP[prevIndex].setState(ISS_ON);
407 }
408
409 TemperatureCompensateModeSP.apply();
410 return true;
411 }
412
413 // Focuser Home on Start Enable/Disable
414 if (FocuserHomeOnStartSP.isNameMatch(name))
415 {
416 int prevIndex = FocuserHomeOnStartSP.findOnSwitchIndex();
417 FocuserHomeOnStartSP.update(states, names, n);
418 if (homeOnStart(DEVICE_FOCUSER, FocuserHomeOnStartSP[INDI_ENABLED].getState() == ISS_ON))
419 {
420 FocuserHomeOnStartSP.setState(IPS_OK);
421 }
422 else
423 {
424 FocuserHomeOnStartSP.reset();
425 FocuserHomeOnStartSP.setState(IPS_ALERT);
426 FocuserHomeOnStartSP[prevIndex].setState(ISS_ON);
427 }
428
429 FocuserHomeOnStartSP.apply();
430 return true;
431 }
432
433 // Rotator Home on Start Enable/Disable
434 if (RotatorHomeOnStartSP.isNameMatch(name))
435 {
436 int prevIndex = RotatorHomeOnStartSP.findOnSwitchIndex();
437 RotatorHomeOnStartSP.update(states, names, n);
438 if (homeOnStart(DEVICE_ROTATOR, RotatorHomeOnStartSP[INDI_ENABLED].getState() == ISS_ON))
439 {
440 RotatorHomeOnStartSP.setState(IPS_OK);
441 }
442 else
443 {
444 RotatorHomeOnStartSP.reset();
445 RotatorHomeOnStartSP.setState(IPS_ALERT);
446 RotatorHomeOnStartSP[prevIndex].setState(ISS_ON);
447 }
448
449 RotatorHomeOnStartSP.apply();
450 return true;
451 }
452
453 // Focuser Backlash enable/disable
454 // if (!strcmp(FocusBacklashSP.name, name))
455 // {
456 // int prevIndex = IUFindOnSwitchIndex(&FocusBacklashSP);
457 // IUUpdateSwitch(&FocusBacklashSP, states, names, n);
458 // if (setBacklashCompensation(DEVICE_FOCUSER, FocusBacklashS[0].s == ISS_ON))
459 // {
460 // FocusBacklashSP.s = IPS_OK;
461 // }
462 // else
463 // {
464 // IUResetSwitch(&FocusBacklashSP);
465 // FocusBacklashSP.s = IPS_ALERT;
466 // FocusBacklashS[prevIndex].s = ISS_ON;
467 // }
468
469 // FocusBacklashSP.apply();
470 // return true;
471 // }
472
473 // Reset to Factory setting
474 if (ResetSP.isNameMatch(name))
475 {
476 ResetSP.reset();
477 if (resetFactory())
478 ResetSP.setState(IPS_OK);
479 else
480 ResetSP.setState(IPS_ALERT);
481
482 ResetSP.apply();
483 return true;
484 }
485
486 // Focser Go to home/center
487 if (FocuserGotoSP.isNameMatch(name))
488 {
489 FocuserGotoSP.update(states, names, n);
490
491 if (FocuserGotoSP[GOTO_HOME].getState() == ISS_ON)
492 {
493 if (home(DEVICE_FOCUSER))
494 {
495 FocuserGotoSP.setState(IPS_BUSY);
498 isFocuserHoming = true;
499 LOG_INFO("Focuser moving to home position...");
500 }
501 else
502 FocuserGotoSP.setState(IPS_ALERT);
503 }
504 else
505 {
506 if (center(DEVICE_FOCUSER))
507 {
508 FocuserGotoSP.setState(IPS_BUSY);
509 LOG_INFO("Focuser moving to center position...");
512 }
513 else
514 FocuserGotoSP.setState(IPS_ALERT);
515 }
516
517 FocuserGotoSP.apply();
518 return true;
519 }
520
521 // Process all rotator properties
522 if (strstr(name, "ROTATOR"))
523 {
524 if (INDI::RotatorInterface::processSwitch(dev, name, states, names, n))
525 return true;
526 }
527
528 // Rotator Go to home/center
529#if 0
530 if (!strcmp(RotatorGotoSP.name, name))
531 {
532 IUUpdateSwitch(&RotatorGotoSP, states, names, n);
533
534 if (RotatorGotoS[GOTO_HOME].s == ISS_ON)
535 {
536 if (home(DEVICE_ROTATOR))
537 {
538 RotatorGotoSP.setState(IPS_BUSY);
539 RotatorAbsPosNP.setState(IPS_BUSY);
540 RotatorAbsPosNP.apply();
541 isRotatorHoming = true;
542 LOG_INFO("Rotator moving to home position...");
543 }
544 else
545 RotatorGotoSP.setState(IPS_ALERT);
546 }
547 else
548 {
549 if (center(DEVICE_ROTATOR))
550 {
551 RotatorGotoSP.setState(IPS_BUSY);
552 LOG_INFO("Rotator moving to center position...");
553 RotatorAbsPosNP.setState(IPS_BUSY);
554 RotatorAbsPosNP.apply();
555 }
556 else
557 RotatorGotoSP.setState(IPS_ALERT);
558 }
559
560 IDSetSwitch(&RotatorGotoSP, nullptr);
561 return true;
562 }
563
564 // Reverse Direction
565 if (!strcmp(ReverseRotatorSP.name, name))
566 {
567 IUUpdateSwitch(&ReverseRotatorSP, states, names, n);
568
569 if (reverseRotator(ReverseRotatorS[0].s == ISS_ON))
571 else
573
574 IDSetSwitch(&ReverseRotatorSP, nullptr);
575 return true;
576 }
577
578 // Halt Rotator
579 if (!strcmp(AbortRotatorSP.name, name))
580 {
581 if (halt(DEVICE_ROTATOR))
582 {
583 RotatorAbsPosNP.s = RotatorAbsAngleNP.s = RotatorGotoSP.setState(IPS_IDLE);
584 RotatorAbsPosNP.apply();
585 RotatorAbsAngleNP.apply();
586 IUResetSwitch(&RotatorGotoSP);
587 IDSetSwitch(&RotatorGotoSP, nullptr);
588
590 }
591 else
593
594 IDSetSwitch(&AbortRotatorSP, nullptr);
595 return true;
596 }
597#endif
598 }
599
600 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
601}
602
603/************************************************************************************
604 *
605* ***********************************************************************************/
606bool Gemini::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
607{
608 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
609 {
610 // Set device nickname to the HUB itself
611 if (HFocusNameTP.isNameMatch(name))
612 {
613 HFocusNameTP.update(texts, names, n);
614 if (setNickname(DEVICE_FOCUSER, HFocusNameTP[DEVICE_FOCUSER].getText())
615 && setNickname(DEVICE_ROTATOR, HFocusNameTP[DEVICE_ROTATOR].getText()))
616 HFocusNameTP.setState(IPS_OK);
617 else
618 HFocusNameTP.setState(IPS_ALERT);
619 HFocusNameTP.apply();
620 return true;
621 }
622 }
623 return INDI::Focuser::ISNewText(dev, name, texts, names, n);
624}
625
626/************************************************************************************
627 *
628* ***********************************************************************************/
629bool Gemini::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
630{
631 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
632 {
633 // Temperature Coefficient
634 if (TemperatureCoeffNP.isNameMatch(name))
635 {
636 TemperatureCoeffNP.update(values, names, n);
637 for (int i = 0; i < n; i++)
638 {
639 if (setTemperatureCompensationCoeff('A' + i, TemperatureCoeffNP[i].getValue()) == false)
640 {
641 LOG_ERROR("Failed to set temperature coefficients.");
642 TemperatureCoeffNP.setState(IPS_ALERT);
643 TemperatureCoeffNP.apply();
644 return false;
645 }
646 }
647
648 TemperatureCoeffNP.setState(IPS_OK);
649 TemperatureCoeffNP.apply();
650 return true;
651 }
652
653 // Focuser Backlash Value
654 // if (!strcmp(FocusBacklashNP.name, name))
655 // {
656 // IUUpdateNumber(&FocusBacklashNP, values, names, n);
657 // if (setBacklashCompensationSteps(DEVICE_FOCUSER, FocusBacklashNP.apply();) == false)
658 // {
659 // LOG_ERROR("Failed to set focuser backlash value.");
660 // FocusBacklashNP.s = IPS_ALERT;
661 // IDSetNumber(&FocusBacklashNP, nullptr);
662 // return false;
663 // }
664
665 // FocusBacklashNP.s = IPS_OK;
666 // IDSetNumber(&FocusBacklashNP, nullptr);
667 // return true;
668 // }
669
670 // Rotator Backlash Value
672 {
673 RotatorBacklashNP.update(values, names, n);
674 if (setBacklashCompensationSteps(DEVICE_ROTATOR, RotatorBacklashNP[0].getValue()) == false)
675 {
676 LOG_ERROR("Failed to set rotator backlash value.");
679 return false;
680 }
681
684 return true;
685 }
686
687 // Set LED intensity to the HUB itself via function setLedLevel()
688 if (LedNP.isNameMatch(name))
689 {
690 LedNP.update(values, names, n);
691 if (setLedLevel(LedNP[0].getValue()))
692 LedNP.setState(IPS_OK);
693 else
694 LedNP.setState(IPS_ALERT);
695 LOGF_INFO("Focuser LED level intensity : %f", LedNP[0].getValue());
696 LedNP.apply();
697 return true;
698 }
699
700 // Set Rotator Absolute Steps
701 if (RotatorAbsPosNP.isNameMatch(name))
702 {
703 RotatorAbsPosNP.update(values, names, n);
704 RotatorAbsPosNP.setState(MoveAbsRotatorTicks(static_cast<uint32_t>(RotatorAbsPosNP[0].value)));
705 RotatorAbsPosNP.apply();
706 return true;
707 }
708
709 if (strstr(name, "ROTATOR"))
710 {
711 if (INDI::RotatorInterface::processNumber(dev, name, values, names, n))
712 return true;
713 }
714
715#if 0
716 // Set Rotator Absolute Steps
717 if (!strcmp(RotatorAbsPosNP.name, name))
718 {
719 IUUpdateNumber(&RotatorAbsPosNP, values, names, n);
720 RotatorAbsPosNP.s = MoveAbsRotatorTicks(static_cast<uint32_t>(RotatorAbsPosN[0].value));
721 RotatorAbsPosNP.apply();
722 return true;
723 }
724
725 // Set Rotator Absolute Angle
726 if (!strcmp(RotatorAbsAngleNP.name, name))
727 {
728 IUUpdateNumber(&RotatorAbsAngleNP, values, names, n);
729 RotatorAbsAngleNP.s = MoveAbsRotatorAngle(RotatorAbsAngleN[0].value);
730 RotatorAbsAngleNP.apply();
731 return true;
732 }
733#endif
734
735 }
736
737 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
738}
739
740/************************************************************************************
741 *
742* ***********************************************************************************/
744{
745 const char *cmd = "<F100GETDNN>";
746 int errcode = 0;
747 char errmsg[MAXRBUF];
748 char response[16];
749 int nbytes_read = 0;
750 int nbytes_written = 0;
751
752 memset(response, 0, sizeof(response));
753
754 LOGF_DEBUG("CMD (%s)", cmd);
755
756 if (isSimulation())
757 {
758 strncpy(response, "Castor", 16);
759 nbytes_read = strlen(response) + 1;
760 }
761 else
762 {
763 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
764 {
765 tty_error_msg(errcode, errmsg, MAXRBUF);
766 LOGF_ERROR("%s", errmsg);
767 return false;
768 }
769
770 if (isResponseOK() == false)
771 return false;
772
773 if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
774 {
775 tty_error_msg(errcode, errmsg, MAXRBUF);
776 LOGF_ERROR("%s", errmsg);
777 return false;
778 }
779 }
780
781 if (nbytes_read > 0)
782 {
783 response[nbytes_read - 1] = '\0';
784 LOGF_DEBUG("RES (%s)", response);
785 LOGF_INFO("%s is detected.", response);
786
787 // Read 'END'
788 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
789
790 tcflush(PortFD, TCIFLUSH);
791
792 return true;
793 }
794
795 tcflush(PortFD, TCIFLUSH);
796 return false;
797}
798
799/************************************************************************************
800 *
801* ***********************************************************************************/
802bool Gemini::getFocusConfig()
803{
804 const char *cmd = "<F100GETCFG>";
805 int errcode = 0;
806 char errmsg[MAXRBUF];
807 char response[64];
808 int nbytes_read = 0;
809 int nbytes_written = 0;
810 char key[16];
811
812 memset(response, 0, sizeof(response));
813
814 LOGF_DEBUG("CMD (%s)", cmd);
815
816 if (isSimulation())
817 {
818 strncpy(response, "!00", sizeof(response));
819 nbytes_read = strlen(response) + 1;
820 }
821 else
822 {
823 tcflush(PortFD, TCIFLUSH);
824
825 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
826 {
827 tty_error_msg(errcode, errmsg, MAXRBUF);
828 LOGF_ERROR("%s", errmsg);
829 return false;
830 }
831
832 if (isResponseOK() == false)
833 return false;
834
835 /*if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
836 {
837 tty_error_msg(errcode, errmsg, MAXRBUF);
838 LOGF_ERROR("%s", errmsg);
839 return false;
840 }*/
841 }
842
843 /*if (nbytes_read > 0)
844 {
845 response[nbytes_read - 1] = '\0';
846 LOGF_DEBUG("RES (%s)", response);
847
848 if ((strcmp(response, "CONFIG1")) && (strcmp(response, "CONFIG2")))
849 return false;
850 }*/
851
852 memset(response, 0, sizeof(response));
853
854 // Nickname
855 if (isSimulation())
856 {
857 strncpy(response, "NickName=Tommy\n", sizeof(response));
858 nbytes_read = strlen(response);
859 }
860 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
861 {
862 tty_error_msg(errcode, errmsg, MAXRBUF);
863 LOGF_ERROR("%s", errmsg);
864 return false;
865 }
866 response[nbytes_read - 1] = '\0';
867 LOGF_DEBUG("RES (%s)", response);
868
869 char nickname[16];
870 int rc = sscanf(response, "%15[^=]=%15[^\n]s", key, nickname);
871
872 if (rc != 2)
873 return false;
874
875 HFocusNameTP.setName(nickname);
876 HFocusNameTP.apply();
877
878 HFocusNameTP.setState(IPS_OK);
879 HFocusNameTP.apply();
880
881 memset(response, 0, sizeof(response));
882
883 // Get Max Position
884 if (isSimulation())
885 {
886 snprintf(response, sizeof(response), "Max Pos = %06d\n", 100000);
887 nbytes_read = strlen(response);
888 }
889 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
890 {
891 tty_error_msg(errcode, errmsg, MAXRBUF);
892 LOGF_ERROR("%s", errmsg);
893 return false;
894 }
895 response[nbytes_read - 1] = '\0';
896 LOGF_DEBUG("RES (%s)", response);
897
898 uint32_t maxPos = 0;
899 rc = sscanf(response, "%15[^=]=%d", key, &maxPos);
900 if (rc == 2)
901 {
902 FocusAbsPosNP[0].setMax(maxPos);
903 FocusAbsPosNP[0].setStep(maxPos / 50.0);
904 FocusAbsPosNP[0].setMin(0);
905
906 FocusRelPosNP[0].setMax(maxPos / 2);
907 FocusRelPosNP[0].setStep(maxPos / 100.0);
908 FocusRelPosNP[0].setMin(0);
909
912
913 maxControllerTicks = maxPos;
914 }
915 else
916 return false;
917
918 memset(response, 0, sizeof(response));
919
920 // Get Device Type
921 if (isSimulation())
922 {
923 strncpy(response, "Dev Typ = A\n", sizeof(response));
924 nbytes_read = strlen(response);
925 }
926 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
927 {
928 tty_error_msg(errcode, errmsg, MAXRBUF);
929 LOGF_ERROR("%s", errmsg);
930 return false;
931 }
932 response[nbytes_read - 1] = '\0';
933 LOGF_DEBUG("RES (%s)", response);
934
935 // Get Status Parameters
936 memset(response, 0, sizeof(response));
937
938 // Temperature Compensation On?
939 if (isSimulation())
940 {
941 snprintf(response, sizeof(response), "TComp ON = %d\n", TemperatureCompensateSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
942 nbytes_read = strlen(response);
943 }
944 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
945 {
946 tty_error_msg(errcode, errmsg, MAXRBUF);
947 LOGF_ERROR("%s", errmsg);
948 return false;
949 }
950 response[nbytes_read - 1] = '\0';
951 LOGF_DEBUG("RES (%s)", response);
952
953 int TCompOn;
954 rc = sscanf(response, "%15[^=]=%d", key, &TCompOn);
955 if (rc != 2)
956 return false;
957
958 TemperatureCompensateSP.reset();
959 TemperatureCompensateSP[INDI_ENABLED].setState(TCompOn ? ISS_ON : ISS_OFF);
960 TemperatureCompensateSP[INDI_ENABLED].setState(TCompOn ? ISS_OFF : ISS_ON);
961 TemperatureCompensateSP.setState(IPS_OK);
962 TemperatureCompensateSP.apply();
963
964 memset(response, 0, sizeof(response));
965
966 // Temperature Coeff A
967 if (isSimulation())
968 {
969 snprintf(response, sizeof(response), "TempCo A = %d\n", (int)TemperatureCoeffNP[FOCUS_A_COEFF].getValue());
970 nbytes_read = strlen(response);
971 }
972 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
973 {
974 tty_error_msg(errcode, errmsg, MAXRBUF);
975 LOGF_ERROR("%s", errmsg);
976 return false;
977 }
978 response[nbytes_read - 1] = '\0';
979 LOGF_DEBUG("RES (%s)", response);
980
981 int TCoeffA;
982 rc = sscanf(response, "%15[^=]=%d", key, &TCoeffA);
983 if (rc != 2)
984 return false;
985
986 TemperatureCoeffNP[FOCUS_A_COEFF].setValue(TCoeffA);
987
988 memset(response, 0, sizeof(response));
989
990 // Temperature Coeff B
991 if (isSimulation())
992 {
993 snprintf(response, sizeof(response), "TempCo B = %d\n", (int)TemperatureCoeffNP[FOCUS_B_COEFF].getValue());
994 nbytes_read = strlen(response);
995 }
996 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
997 {
998 tty_error_msg(errcode, errmsg, MAXRBUF);
999 LOGF_ERROR("%s", errmsg);
1000 return false;
1001 }
1002 response[nbytes_read - 1] = '\0';
1003 LOGF_DEBUG("RES (%s)", response);
1004
1005 int TCoeffB;
1006 rc = sscanf(response, "%15[^=]=%d", key, &TCoeffB);
1007 if (rc != 2)
1008 return false;
1009
1010 TemperatureCoeffNP[FOCUS_B_COEFF].setValue(TCoeffB);
1011
1012 memset(response, 0, sizeof(response));
1013
1014 // Temperature Coeff C
1015 if (isSimulation())
1016 {
1017 snprintf(response, sizeof(response), "TempCo C = %d\n", (int)TemperatureCoeffNP[FOCUS_C_COEFF].getValue());
1018 nbytes_read = strlen(response);
1019 }
1020 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1021 {
1022 tty_error_msg(errcode, errmsg, MAXRBUF);
1023 LOGF_ERROR("%s", errmsg);
1024 return false;
1025 }
1026 response[nbytes_read - 1] = '\0';
1027 LOGF_DEBUG("RES (%s)", response);
1028
1029 int TCoeffC;
1030 rc = sscanf(response, "%15[^=]=%d", key, &TCoeffC);
1031 if (rc != 2)
1032 return false;
1033
1034 TemperatureCoeffNP[FOCUS_C_COEFF].setValue(TCoeffC);
1035
1036 memset(response, 0, sizeof(response));
1037
1038 // Temperature Coeff D
1039 if (isSimulation())
1040 {
1041 snprintf(response, sizeof(response), "TempCo D = %d\n", (int)TemperatureCoeffNP[FOCUS_D_COEFF].getValue());
1042 nbytes_read = strlen(response);
1043 }
1044 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1045 {
1046 tty_error_msg(errcode, errmsg, MAXRBUF);
1047 LOGF_ERROR("%s", errmsg);
1048 return false;
1049 }
1050 response[nbytes_read - 1] = '\0';
1051 LOGF_DEBUG("RES (%s)", response);
1052
1053 int TCoeffD;
1054 rc = sscanf(response, "%15[^=]=%d", key, &TCoeffD);
1055 if (rc != 2)
1056 return false;
1057
1058 TemperatureCoeffNP[FOCUS_D_COEFF].setValue(TCoeffD);
1059
1060 memset(response, 0, sizeof(response));
1061
1062 // Temperature Coeff E
1063 if (isSimulation())
1064 {
1065 snprintf(response, sizeof(response), "TempCo E = %d\n", (int)TemperatureCoeffNP[FOCUS_E_COEFF].getValue());
1066 nbytes_read = strlen(response);
1067 }
1068 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1069 {
1070 tty_error_msg(errcode, errmsg, MAXRBUF);
1071 LOGF_ERROR("%s", errmsg);
1072 return false;
1073 }
1074 response[nbytes_read - 1] = '\0';
1075 LOGF_DEBUG("RES (%s)", response);
1076
1077 int TCoeffE;
1078 rc = sscanf(response, "%15[^=]=%d", key, &TCoeffE);
1079 if (rc != 2)
1080 return false;
1081
1082 TemperatureCoeffNP[FOCUS_E_COEFF].setValue(TCoeffE);
1083
1084 TemperatureCoeffNP.setState(IPS_OK);
1085 TemperatureCoeffNP.apply();
1086
1087 memset(response, 0, sizeof(response));
1088
1089 // Temperature Compensation Mode
1090 if (isSimulation())
1091 {
1092 snprintf(response, sizeof(response), "TC Mode = %c\n", 'C');
1093 nbytes_read = strlen(response);
1094 }
1095 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1096 {
1097 tty_error_msg(errcode, errmsg, MAXRBUF);
1098 LOGF_ERROR("%s", errmsg);
1099 return false;
1100 }
1101 response[nbytes_read - 1] = '\0';
1102 LOGF_DEBUG("RES (%s)", response);
1103
1104 char compensateMode;
1105 rc = sscanf(response, "%15[^=]= %c", key, &compensateMode);
1106 if (rc != 2)
1107 return false;
1108
1109 TemperatureCompensateModeSP.reset();
1110 int index = compensateMode - 'A';
1111 if (index >= 0 && index <= 5)
1112 {
1113 TemperatureCompensateModeSP[index].setState(ISS_ON);
1114 TemperatureCompensateModeSP.setState(IPS_OK);
1115 }
1116 else
1117 {
1118 LOGF_ERROR("Invalid index %d for compensation mode.", index);
1119 TemperatureCompensateModeSP.setState(IPS_ALERT);
1120 }
1121
1122 TemperatureCompensateModeSP.apply();
1123
1124 // Backlash Compensation
1125 memset(response, 0, sizeof(response));
1126 if (isSimulation())
1127 {
1128 snprintf(response, sizeof(response), "BLC En = %d\n", FocusBacklashSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
1129 nbytes_read = strlen(response);
1130 }
1131 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1132 {
1133 tty_error_msg(errcode, errmsg, MAXRBUF);
1134 LOGF_ERROR("%s", errmsg);
1135 return false;
1136 }
1137 response[nbytes_read - 1] = '\0';
1138 LOGF_DEBUG("RES (%s)", response);
1139
1140 int BLCCompensate;
1141 rc = sscanf(response, "%15[^=]=%d", key, &BLCCompensate);
1142 if (rc != 2)
1143 return false;
1144
1150
1151 // Backlash Value
1152 memset(response, 0, sizeof(response));
1153 if (isSimulation())
1154 {
1155 snprintf(response, sizeof(response), "BLC Stps = %d\n", 50);
1156 nbytes_read = strlen(response);
1157 }
1158 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1159 {
1160 tty_error_msg(errcode, errmsg, MAXRBUF);
1161 LOGF_ERROR("%s", errmsg);
1162 return false;
1163 }
1164 response[nbytes_read - 1] = '\0';
1165 LOGF_DEBUG("RES (%s)", response);
1166
1167 int BLCValue;
1168 rc = sscanf(response, "%15[^=]=%d", key, &BLCValue);
1169 if (rc != 2)
1170 return false;
1171
1172 FocusBacklashNP[0].setValue(BLCValue);
1175
1176 // Temperature Compensation on Start
1177 memset(response, 0, sizeof(response));
1178 if (isSimulation())
1179 {
1180 snprintf(response, sizeof(response), "TC Start = %d\n",
1181 TemperatureCompensateOnStartSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
1182 nbytes_read = strlen(response);
1183 }
1184 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1185 {
1186 tty_error_msg(errcode, errmsg, MAXRBUF);
1187 LOGF_ERROR("%s", errmsg);
1188 return false;
1189 }
1190 response[nbytes_read - 1] = '\0';
1191 LOGF_DEBUG("RES (%s)", response);
1192
1193 int TCOnStart;
1194 rc = sscanf(response, "%15[^=]=%d", key, &TCOnStart);
1195 if (rc != 2)
1196 return false;
1197
1198 TemperatureCompensateOnStartSP.reset();
1199 TemperatureCompensateOnStartSP[INDI_ENABLED].setState(TCOnStart ? ISS_ON : ISS_OFF);
1200 TemperatureCompensateOnStartSP[INDI_DISABLED].setState(TCOnStart ? ISS_OFF : ISS_ON);
1201 TemperatureCompensateOnStartSP.setState(IPS_OK);
1202 TemperatureCompensateOnStartSP.apply();
1203
1204 // Get Status Parameters
1205 memset(response, 0, sizeof(response));
1206
1207 // Home on start on?
1208 if (isSimulation())
1209 {
1210 snprintf(response, sizeof(response), "HOnStart = %d\n", FocuserHomeOnStartSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
1211 nbytes_read = strlen(response);
1212 }
1213 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1214 {
1215 tty_error_msg(errcode, errmsg, MAXRBUF);
1216 LOGF_ERROR("%s", errmsg);
1217 return false;
1218 }
1219 response[nbytes_read - 1] = '\0';
1220 LOGF_DEBUG("RES (%s)", response);
1221
1222 int StartOnHome;
1223 rc = sscanf(response, "%15[^=]=%d", key, &StartOnHome);
1224 if (rc != 2)
1225 return false;
1226
1227 FocuserHomeOnStartSP.reset();
1228 FocuserHomeOnStartSP[INDI_ENABLED].setState(StartOnHome ? ISS_ON : ISS_OFF);
1229 FocuserHomeOnStartSP[INDI_DISABLED].setState(StartOnHome ? ISS_OFF : ISS_ON);
1230 FocuserHomeOnStartSP.setState(IPS_OK);
1231 FocuserHomeOnStartSP.apply();
1232
1233 // Added By Philippe Besson the 28th of June for 'END' evaluation
1234 // END is reached
1235 memset(response, 0, sizeof(response));
1236 if (isSimulation())
1237 {
1238 strncpy(response, "END\n", 16);
1239 nbytes_read = strlen(response);
1240 }
1241 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1242 {
1243 tty_error_msg(errcode, errmsg, MAXRBUF);
1244 LOGF_ERROR("%s", errmsg);
1245 return false;
1246 }
1247
1248 if (nbytes_read > 0)
1249 {
1250 response[nbytes_read - 1] = '\0';
1251
1252 // Display the response to be sure to have read the complete TTY Buffer.
1253 LOGF_DEBUG("RES (%s)", response);
1254
1255 if (strcmp(response, "END"))
1256 return false;
1257 }
1258 // End of added code by Philippe Besson
1259
1260 tcflush(PortFD, TCIFLUSH);
1261
1263
1264 return true;
1265}
1266
1267/************************************************************************************
1268 *
1269* ***********************************************************************************/
1270bool Gemini::getRotatorStatus()
1271{
1272 const char *cmd = "<R100GETSTA>";
1273 int errcode = 0;
1274 char errmsg[MAXRBUF];
1275 char response[32];
1276 int nbytes_read = 0;
1277 int nbytes_written = 0;
1278 char key[16];
1279
1280 memset(response, 0, sizeof(response));
1281
1282 LOGF_DEBUG("CMD (%s)", cmd);
1283
1284 if (isSimulation())
1285 {
1286 strncpy(response, "!00", 16);
1287 nbytes_read = strlen(response) + 1;
1288 }
1289 else
1290 {
1291 tcflush(PortFD, TCIFLUSH);
1292
1293 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
1294 {
1295 tty_error_msg(errcode, errmsg, MAXRBUF);
1296 LOGF_ERROR("%s", errmsg);
1297 return false;
1298 }
1299
1300 if (isResponseOK() == false)
1301 return false;
1302
1303 /*if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1304 {
1305 tty_error_msg(errcode, errmsg, MAXRBUF);
1306 LOGF_ERROR("%s", errmsg);
1307 return false;
1308 }*/
1309 }
1310
1312 // #1 Get Current Position
1314 memset(response, 0, sizeof(response));
1315 if (isSimulation())
1316 {
1317 snprintf(response, 32, "CurrStep = %06d\n", rotatorSimPosition);
1318 nbytes_read = strlen(response);
1319 }
1320 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1321 {
1322 tty_error_msg(errcode, errmsg, MAXRBUF);
1323 LOGF_ERROR("%s", errmsg);
1324 return false;
1325 }
1326 response[nbytes_read - 1] = '\0';
1327 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1328
1329 int currPos = 0;
1330 int rc = sscanf(response, "%15[^=]=%d", key, &currPos);
1331 if (rc == 2)
1332 {
1333 // Do not spam unless there is an actual change
1334 if (RotatorAbsPosNP[0].getValue() != currPos)
1335 {
1336 RotatorAbsPosNP[0].setValue(currPos);
1337 RotatorAbsPosNP.apply();
1338 }
1339 }
1340 else
1341 return false;
1342
1344 // #2 Get Target Position
1346 memset(response, 0, sizeof(response));
1347 if (isSimulation())
1348 {
1349 snprintf(response, 32, "TargStep = %06d\n", targetFocuserPosition);
1350 nbytes_read = strlen(response);
1351 }
1352 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1353 {
1354 tty_error_msg(errcode, errmsg, MAXRBUF);
1355 LOGF_ERROR("%s", errmsg);
1356 return false;
1357 }
1358 response[nbytes_read - 1] = '\0';
1359 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1360
1362 // #3 Get Current PA
1364 memset(response, 0, sizeof(response));
1365 if (isSimulation())
1366 {
1367 snprintf(response, 32, "CurenPA = %06d\n", rotatorSimPA);
1368 nbytes_read = strlen(response);
1369 }
1370 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1371 {
1372 tty_error_msg(errcode, errmsg, MAXRBUF);
1373 LOGF_ERROR("%s", errmsg);
1374 return false;
1375 }
1376 response[nbytes_read - 1] = '\0';
1377 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1378
1379 int currPA = 0;
1380 rc = sscanf(response, "%15[^=]=%d", key, &currPA);
1381 if (rc == 2)
1382 {
1383 // Only send when above a threshold
1384 double diffPA = fabs(GotoRotatorNP[0].getValue() - currPA / 1000.0);
1385 if (diffPA >= 0.01)
1386 {
1387 GotoRotatorNP[0].setValue(currPA / 1000.0);
1389 }
1390 }
1391 else
1392 return false;
1393
1395 // #3 Get Target PA
1397 memset(response, 0, sizeof(response));
1398 if (isSimulation())
1399 {
1400 snprintf(response, 32, "TargetPA = %06d\n", targetFocuserPosition);
1401 nbytes_read = strlen(response);
1402 }
1403 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1404 {
1405 tty_error_msg(errcode, errmsg, MAXRBUF);
1406 LOGF_ERROR("%s", errmsg);
1407 return false;
1408 }
1409 response[nbytes_read - 1] = '\0';
1410 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1411
1412 // Get Status Parameters
1413
1415 // #5 is Moving?
1417 memset(response, 0, sizeof(response));
1418 if (isSimulation())
1419 {
1420 snprintf(response, 32, "IsMoving = %d\n", (rotatorSimStatus[STATUS_MOVING] == ISS_ON) ? 1 : 0);
1421 nbytes_read = strlen(response);
1422 }
1423 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1424 {
1425 tty_error_msg(errcode, errmsg, MAXRBUF);
1426 LOGF_ERROR("%s", errmsg);
1427 return false;
1428 }
1429 response[nbytes_read - 1] = '\0';
1430 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1431
1432 int isMoving;
1433 rc = sscanf(response, "%15[^=]=%d", key, &isMoving);
1434 if (rc != 2)
1435 return false;
1436
1437 RotatorStatusLP[STATUS_MOVING].setState(isMoving ? IPS_BUSY : IPS_IDLE);
1438
1440 // #6 is Homing?
1442 memset(response, 0, sizeof(response));
1443 if (isSimulation())
1444 {
1445 snprintf(response, 32, "IsHoming = %d\n", (rotatorSimStatus[STATUS_HOMING] == ISS_ON) ? 1 : 0);
1446 nbytes_read = strlen(response);
1447 }
1448 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1449 {
1450 tty_error_msg(errcode, errmsg, MAXRBUF);
1451 LOGF_ERROR("%s", errmsg);
1452 return false;
1453 }
1454 response[nbytes_read - 1] = '\0';
1455 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1456
1457 int _isHoming;
1458 rc = sscanf(response, "%15[^=]=%d", key, &_isHoming);
1459 if (rc != 2)
1460 return false;
1461
1462 RotatorStatusLP[STATUS_HOMING].setState(_isHoming ? IPS_BUSY : IPS_IDLE);
1463
1464 // We set that isHoming in process, but we don't set it to false here it must be reset in TimerHit
1465 if (RotatorStatusLP[STATUS_HOMING].getState() == IPS_BUSY)
1466 isRotatorHoming = true;
1467
1469 // #6 is Homed?
1471 memset(response, 0, sizeof(response));
1472 if (isSimulation())
1473 {
1474 snprintf(response, 32, "IsHomed = %d\n", (rotatorSimStatus[STATUS_HOMED] == ISS_ON) ? 1 : 0);
1475 nbytes_read = strlen(response);
1476 }
1477 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1478 {
1479 tty_error_msg(errcode, errmsg, MAXRBUF);
1480 LOGF_ERROR("%s", errmsg);
1481 return false;
1482 }
1483 response[nbytes_read - 1] = '\0';
1484 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1485
1486 int isHomed;
1487 rc = sscanf(response, "%15[^=]=%d", key, &isHomed);
1488 if (rc != 2)
1489 return false;
1490
1491 RotatorStatusLP[STATUS_HOMED].setState(isHomed ? IPS_OK : IPS_IDLE);
1492 RotatorStatusLP.apply();
1493
1494 // Added By Philippe Besson the 28th of June for 'END' evaluation
1495 // END is reached
1496 memset(response, 0, sizeof(response));
1497 if (isSimulation())
1498 {
1499 strncpy(response, "END\n", 16);
1500 nbytes_read = strlen(response);
1501 }
1502 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1503 {
1504 tty_error_msg(errcode, errmsg, MAXRBUF);
1505 LOGF_ERROR("%s", errmsg);
1506 return false;
1507 }
1508
1509 if (nbytes_read > 0)
1510 {
1511 response[nbytes_read - 1] = '\0';
1512
1513 // Display the response to be sure to have read the complete TTY Buffer.
1514 LOGF_DEBUG("RES (%s)", response);
1515
1516 if (strcmp(response, "END"))
1517 {
1518 LOG_WARN("Invalid END response.");
1519 return false;
1520 }
1521 }
1522 // End of added code by Philippe Besson
1523
1524 tcflush(PortFD, TCIFLUSH);
1525
1526 return true;
1527
1528}
1529
1530/************************************************************************************
1531 *
1532* ***********************************************************************************/
1533bool Gemini::getRotatorConfig()
1534{
1535 const char *cmd = "<R100GETCFG>";
1536 int errcode = 0;
1537 char errmsg[MAXRBUF];
1538 char response[64];
1539 int nbytes_read = 0;
1540 int nbytes_written = 0;
1541 char key[16];
1542
1543 memset(response, 0, sizeof(response));
1544
1545 LOGF_DEBUG("CMD (%s)", cmd);
1546
1547 if (isSimulation())
1548 {
1549 strncpy(response, "!00", sizeof(response));
1550 nbytes_read = strlen(response) + 1;
1551 }
1552 else
1553 {
1554 tcflush(PortFD, TCIFLUSH);
1555
1556 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
1557 {
1558 tty_error_msg(errcode, errmsg, MAXRBUF);
1559 LOGF_ERROR("%s", errmsg);
1560 return false;
1561 }
1562
1563 if (isResponseOK() == false)
1564 return false;
1565
1566 /*if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1567 {
1568 tty_error_msg(errcode, errmsg, MAXRBUF);
1569 LOGF_ERROR("%s", errmsg);
1570 return false;
1571 }*/
1572 }
1573
1574 /*if (nbytes_read > 0)
1575 {
1576 response[nbytes_read - 1] = '\0';
1577 LOGF_DEBUG("RES (%s)", response);
1578
1579 if ((strcmp(response, "CONFIG1")) && (strcmp(response, "CONFIG2")))
1580 return false;
1581 }*/
1582
1583 memset(response, 0, sizeof(response));
1585 // Nickname
1587 if (isSimulation())
1588 {
1589 strncpy(response, "NickName=Juli\n", sizeof(response));
1590 nbytes_read = strlen(response);
1591 }
1592 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1593 {
1594 tty_error_msg(errcode, errmsg, MAXRBUF);
1595 LOGF_ERROR("%s", errmsg);
1596 return false;
1597 }
1598 response[nbytes_read - 1] = '\0';
1599 LOGF_DEBUG("RES (%s)", response);
1600
1601 char nickname[16];
1602 int rc = sscanf(response, "%15[^=]=%15[^\n]s", key, nickname);
1603
1604 if (rc != 2)
1605 return false;
1606
1607 HFocusNameTP[DEVICE_ROTATOR].setText(nickname);
1608 HFocusNameTP.setState(IPS_OK);
1609 HFocusNameTP.apply();
1610
1611 memset(response, 0, sizeof(response));
1612
1614 // Get Max steps
1616 if (isSimulation())
1617 {
1618 snprintf(response, sizeof(response), "MaxSteps = %06d\n", 100000);
1619 nbytes_read = strlen(response);
1620 }
1621 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1622 {
1623 tty_error_msg(errcode, errmsg, MAXRBUF);
1624 LOGF_ERROR("%s", errmsg);
1625 return false;
1626 }
1627 response[nbytes_read - 1] = '\0';
1628 LOGF_DEBUG("RES (%s)", response);
1629
1630 uint32_t maxPos = 0;
1631 rc = sscanf(response, "%15[^=]=%d", key, &maxPos);
1632 if (rc == 2)
1633 {
1634 RotatorAbsPosNP[0].setMin(0);
1635 RotatorAbsPosNP[0].setMax(maxPos);
1636 RotatorAbsPosNP[0].setStep(maxPos / 50.0);
1637 RotatorAbsPosNP.updateMinMax();
1638 }
1639 else
1640 return false;
1641
1642 memset(response, 0, sizeof(response));
1643
1645 // Get Device Type
1647 if (isSimulation())
1648 {
1649 strncpy(response, "Dev Type = B\n", sizeof(response));
1650 nbytes_read = strlen(response);
1651 }
1652 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1653 {
1654 tty_error_msg(errcode, errmsg, MAXRBUF);
1655 LOGF_ERROR("%s", errmsg);
1656 return false;
1657 }
1658 response[nbytes_read - 1] = '\0';
1659 LOGF_DEBUG("RES (%s)", response);
1660
1661 // Get Status Parameters
1662 memset(response, 0, sizeof(response));
1663
1665 // Backlash Compensation
1667 memset(response, 0, sizeof(response));
1668 if (isSimulation())
1669 {
1670 snprintf(response, sizeof(response), "BLCSteps = %d\n", RotatorBacklashSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
1671 nbytes_read = strlen(response);
1672 }
1673 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1674 {
1675 tty_error_msg(errcode, errmsg, MAXRBUF);
1676 LOGF_ERROR("%s", errmsg);
1677 return false;
1678 }
1679 response[nbytes_read - 1] = '\0';
1680 LOGF_DEBUG("RES (%s)", response);
1681
1682 int BLCCompensate;
1683 rc = sscanf(response, "%15[^=]=%d", key, &BLCCompensate);
1684 if (rc != 2)
1685 return false;
1686
1692
1694 // Backlash Value
1696 memset(response, 0, sizeof(response));
1697 if (isSimulation())
1698 {
1699 snprintf(response, sizeof(response), "BLCSteps = %d\n", 50);
1700 nbytes_read = strlen(response);
1701 }
1702 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1703 {
1704 tty_error_msg(errcode, errmsg, MAXRBUF);
1705 LOGF_ERROR("%s", errmsg);
1706 return false;
1707 }
1708 response[nbytes_read - 1] = '\0';
1709 LOGF_DEBUG("RES (%s)", response);
1710
1711 int BLCValue;
1712 rc = sscanf(response, "%15[^=]=%d", key, &BLCValue);
1713 if (rc != 2)
1714 return false;
1715
1716 RotatorBacklashNP[0].setValue(BLCValue);
1719
1721 // Home on start on?
1723 memset(response, 0, sizeof(response));
1724 if (isSimulation())
1725 {
1726 snprintf(response, sizeof(response), "HOnStart = %d\n", RotatorHomeOnStartSP[INDI_ENABLED].getState() == ISS_ON ? 1 : 0);
1727 nbytes_read = strlen(response);
1728 }
1729 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1730 {
1731 tty_error_msg(errcode, errmsg, MAXRBUF);
1732 LOGF_ERROR("%s", errmsg);
1733 return false;
1734 }
1735 response[nbytes_read - 1] = '\0';
1736 LOGF_DEBUG("RES (%s)", response);
1737
1738 int StartOnHome;
1739 rc = sscanf(response, "%15[^=]=%d", key, &StartOnHome);
1740 if (rc != 2)
1741 return false;
1742
1743 RotatorHomeOnStartSP.reset();
1744 RotatorHomeOnStartSP[INDI_ENABLED].setState( StartOnHome ? ISS_ON : ISS_OFF);
1745 RotatorHomeOnStartSP[INDI_DISABLED].setState(StartOnHome ? ISS_OFF : ISS_ON);
1746 RotatorHomeOnStartSP.setState(IPS_OK);
1747 RotatorHomeOnStartSP.apply();
1748
1750 // Reverse?
1752 memset(response, 0, sizeof(response));
1753 if (isSimulation())
1754 {
1755 snprintf(response, 32, "Reverse = %d\n", (rotatorSimStatus[STATUS_REVERSE] == ISS_ON) ? 1 : 0);
1756 nbytes_read = strlen(response);
1757 }
1758 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1759 {
1760 tty_error_msg(errcode, errmsg, MAXRBUF);
1761 LOGF_ERROR("%s", errmsg);
1762 return false;
1763 }
1764 response[nbytes_read - 1] = '\0';
1765 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1766
1767 int reverse;
1768 rc = sscanf(response, "%15[^=]=%d", key, &reverse);
1769 if (rc != 2)
1770 return false;
1771
1772 RotatorStatusLP[STATUS_REVERSE].setState(reverse ? IPS_OK : IPS_IDLE);
1773
1774 // If reverse is enable and switch shows disabled, let's change that
1775 // same thing is reverse is disabled but switch is enabled
1776 if ((reverse && ReverseRotatorSP[1].getState() == ISS_ON) || (!reverse && ReverseRotatorSP[0].getState() == ISS_ON))
1777 {
1779 ReverseRotatorSP[0].setState((reverse == 1) ? ISS_ON : ISS_OFF);
1780 ReverseRotatorSP[1].setState((reverse == 0) ? ISS_ON : ISS_OFF);
1782 }
1783
1784 RotatorStatusLP.setState(IPS_OK);
1785 RotatorStatusLP.apply();
1786
1788 // Max Speed - Not used
1790 memset(response, 0, sizeof(response));
1791 if (isSimulation())
1792 {
1793 snprintf(response, 32, "MaxSpeed = %d\n", 800);
1794 nbytes_read = strlen(response);
1795 }
1796 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1797 {
1798 tty_error_msg(errcode, errmsg, MAXRBUF);
1799 LOGF_ERROR("%s", errmsg);
1800 return false;
1801 }
1802 response[nbytes_read - 1] = '\0';
1803 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1804
1805 // Added By Philippe Besson the 28th of June for 'END' evaluation
1806 // END is reached
1807 memset(response, 0, sizeof(response));
1808 if (isSimulation())
1809 {
1810 strncpy(response, "END\n", 16);
1811 nbytes_read = strlen(response);
1812 }
1813 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1814 {
1815 tty_error_msg(errcode, errmsg, MAXRBUF);
1816 LOGF_ERROR("%s", errmsg);
1817 return false;
1818 }
1819
1820 if (nbytes_read > 0)
1821 {
1822 response[nbytes_read - 1] = '\0';
1823
1824 // Display the response to be sure to have read the complete TTY Buffer.
1825 LOGF_DEBUG("RES (%s)", response);
1826
1827 if (strcmp(response, "END"))
1828 return false;
1829 }
1830 // End of added code by Philippe Besson
1831
1832 tcflush(PortFD, TCIFLUSH);
1833
1835
1836 return true;
1837}
1838
1839/************************************************************************************
1840 *
1841* ***********************************************************************************/
1842bool Gemini::getFocusStatus()
1843{
1844 const char *cmd = "<F100GETSTA>";
1845 int errcode = 0;
1846 char errmsg[MAXRBUF];
1847 char response[32];
1848 int nbytes_read = 0;
1849 int nbytes_written = 0;
1850 char key[16];
1851
1852 memset(response, 0, sizeof(response));
1853
1854 LOGF_DEBUG("CMD (%s)", cmd);
1855
1856 if (isSimulation())
1857 {
1858 strncpy(response, "!00", 16);
1859 nbytes_read = strlen(response) + 1;
1860 }
1861 else
1862 {
1863 tcflush(PortFD, TCIFLUSH);
1864
1865 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
1866 {
1867 tty_error_msg(errcode, errmsg, MAXRBUF);
1868 LOGF_ERROR("%s", errmsg);
1869 return false;
1870 }
1871
1872 if (isResponseOK() == false)
1873 return false;
1874
1875 /*if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1876 {
1877 tty_error_msg(errcode, errmsg, MAXRBUF);
1878 LOGF_ERROR("%s", errmsg);
1879 return false;
1880 }*/
1881 }
1882
1883 // Get Temperature
1884 memset(response, 0, sizeof(response));
1885 if (isSimulation())
1886 {
1887 //strncpy(response, "CurrTemp = +21.7\n", 16); // #PS: incorrect, lost last character
1888 strcpy(response, "CurrTemp = +21.7\n");
1889 nbytes_read = strlen(response);
1890 }
1891 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1892 {
1893 tty_error_msg(errcode, errmsg, MAXRBUF);
1894 LOGF_ERROR("%s", errmsg);
1895 return false;
1896 }
1897
1898 if (nbytes_read > 0)
1899 response[nbytes_read - 1] = '\0';
1900
1901 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1902
1903 float temperature = 0;
1904 int rc = sscanf(response, "%15[^=]=%f", key, &temperature);
1905 if (rc == 2)
1906 {
1907 TemperatureNP[0].setValue(temperature);
1908 TemperatureNP.apply();
1909 }
1910 else
1911 {
1912 char np[8];
1913 int rc = sscanf(response, "%15[^=]= %s", key, np);
1914
1915 if (rc != 2 || strcmp(np, "NP"))
1916 {
1917 if (TemperatureNP.getState() != IPS_ALERT)
1918 {
1919 TemperatureNP.setState(IPS_ALERT);
1920 TemperatureNP.apply();
1921 }
1922 return false;
1923 }
1924 }
1925
1927 // #1 Get Current Position
1929 memset(response, 0, sizeof(response));
1930 if (isSimulation())
1931 {
1932 snprintf(response, 32, "CurrStep = %06d\n", focuserSimPosition);
1933 nbytes_read = strlen(response);
1934 }
1935 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1936 {
1937 tty_error_msg(errcode, errmsg, MAXRBUF);
1938 LOGF_ERROR("%s", errmsg);
1939 return false;
1940 }
1941 response[nbytes_read - 1] = '\0';
1942 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1943
1944 uint32_t currPos = 0;
1945 rc = sscanf(response, "%15[^=]=%d", key, &currPos);
1946 if (rc == 2)
1947 {
1948 FocusAbsPosNP[0].setValue(currPos);
1950 }
1951 else
1952 return false;
1953
1955 // #2 Get Target Position
1957 memset(response, 0, sizeof(response));
1958 if (isSimulation())
1959 {
1960 snprintf(response, 32, "TargStep = %06d\n", targetFocuserPosition);
1961 nbytes_read = strlen(response);
1962 }
1963 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1964 {
1965 tty_error_msg(errcode, errmsg, MAXRBUF);
1966 LOGF_ERROR("%s", errmsg);
1967 return false;
1968 }
1969 response[nbytes_read - 1] = '\0';
1970 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1971
1972 // Get Status Parameters
1973
1975 // #3 is Moving?
1977 memset(response, 0, sizeof(response));
1978 if (isSimulation())
1979 {
1980 snprintf(response, 32, "IsMoving = %d\n", (focuserSimStatus[STATUS_MOVING] == ISS_ON) ? 1 : 0);
1981 nbytes_read = strlen(response);
1982 }
1983 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
1984 {
1985 tty_error_msg(errcode, errmsg, MAXRBUF);
1986 LOGF_ERROR("%s", errmsg);
1987 return false;
1988 }
1989 response[nbytes_read - 1] = '\0';
1990 DEBUGF(DBG_FOCUS, "RES (%s)", response);
1991
1992 int isMoving;
1993 rc = sscanf(response, "%15[^=]=%d", key, &isMoving);
1994 if (rc != 2)
1995 return false;
1996
1997 FocuserStatusLP[STATUS_MOVING].setState(isMoving ? IPS_BUSY : IPS_IDLE);
1998
2000 // #4 is Homing?
2002 memset(response, 0, sizeof(response));
2003 if (isSimulation())
2004 {
2005 snprintf(response, 32, "IsHoming = %d\n", (focuserSimStatus[STATUS_HOMING] == ISS_ON) ? 1 : 0);
2006 nbytes_read = strlen(response);
2007 }
2008 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2009 {
2010 tty_error_msg(errcode, errmsg, MAXRBUF);
2011 LOGF_ERROR("%s", errmsg);
2012 return false;
2013 }
2014 response[nbytes_read - 1] = '\0';
2015 DEBUGF(DBG_FOCUS, "RES (%s)", response);
2016
2017 int _isHoming;
2018 rc = sscanf(response, "%15[^=]=%d", key, &_isHoming);
2019 if (rc != 2)
2020 return false;
2021
2022 FocuserStatusLP[STATUS_HOMING].setState(_isHoming ? IPS_BUSY : IPS_IDLE);
2023 // For relative focusers home is not applicable.
2024 if (isFocuserAbsolute == false)
2025 FocuserStatusLP[STATUS_HOMING].setState(IPS_IDLE);
2026
2027 // We set that isHoming in process, but we don't set it to false here it must be reset in TimerHit
2028 if (FocuserStatusLP[STATUS_HOMING].getState() == IPS_BUSY)
2029 isFocuserHoming = true;
2030
2032 // #6 is Homed?
2034 memset(response, 0, sizeof(response));
2035 if (isSimulation())
2036 {
2037 snprintf(response, 32, "IsHomed = %d\n", (focuserSimStatus[STATUS_HOMED] == ISS_ON) ? 1 : 0);
2038 nbytes_read = strlen(response);
2039 }
2040 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2041 {
2042 tty_error_msg(errcode, errmsg, MAXRBUF);
2043 LOGF_ERROR("%s", errmsg);
2044 return false;
2045 }
2046 response[nbytes_read - 1] = '\0';
2047 DEBUGF(DBG_FOCUS, "RES (%s)", response);
2048
2049 int isHomed;
2050 rc = sscanf(response, "%15[^=]=%d", key, &isHomed);
2051 if (rc != 2)
2052 return false;
2053
2054 FocuserStatusLP[STATUS_HOMED].setState(isHomed ? IPS_OK : IPS_IDLE);
2055 // For relative focusers home is not applicable.
2056 if (isFocuserAbsolute == false)
2057 FocuserStatusLP[STATUS_HOMED].setState(IPS_IDLE);
2058
2060 // #7 Temperature probe?
2062 memset(response, 0, sizeof(response));
2063 if (isSimulation())
2064 {
2065 snprintf(response, 32, "TempProb = %d\n", (focuserSimStatus[STATUS_TMPPROBE] == ISS_ON) ? 1 : 0);
2066 nbytes_read = strlen(response);
2067 }
2068 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2069 {
2070 tty_error_msg(errcode, errmsg, MAXRBUF);
2071 LOGF_ERROR("%s", errmsg);
2072 return false;
2073 }
2074 response[nbytes_read - 1] = '\0';
2075 DEBUGF(DBG_FOCUS, "RES (%s)", response);
2076
2077 int TmpProbe;
2078 rc = sscanf(response, "%15[^=]=%d", key, &TmpProbe);
2079 if (rc != 2)
2080 return false;
2081
2082 FocuserStatusLP[STATUS_TMPPROBE].setState(TmpProbe ? IPS_OK : IPS_IDLE);
2083
2085 // #8 Remote IO?
2087 memset(response, 0, sizeof(response));
2088 if (isSimulation())
2089 {
2090 snprintf(response, 32, "RemoteIO = %d\n", (focuserSimStatus[STATUS_REMOTEIO] == ISS_ON) ? 1 : 0);
2091 nbytes_read = strlen(response);
2092 }
2093 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2094 {
2095 tty_error_msg(errcode, errmsg, MAXRBUF);
2096 LOGF_ERROR("%s", errmsg);
2097 return false;
2098 }
2099 response[nbytes_read - 1] = '\0';
2100 DEBUGF(DBG_FOCUS, "RES (%s)", response);
2101
2102 int RemoteIO;
2103 rc = sscanf(response, "%15[^=]=%d", key, &RemoteIO);
2104 if (rc != 2)
2105 return false;
2106
2107 FocuserStatusLP[STATUS_REMOTEIO].setState(RemoteIO ? IPS_OK : IPS_IDLE);
2108
2110 // #9 Hand controller?
2112 memset(response, 0, sizeof(response));
2113 if (isSimulation())
2114 {
2115 snprintf(response, 32, "HCStatus = %d\n", (focuserSimStatus[STATUS_HNDCTRL] == ISS_ON) ? 1 : 0);
2116 nbytes_read = strlen(response);
2117 }
2118 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2119 {
2120 tty_error_msg(errcode, errmsg, MAXRBUF);
2121 LOGF_ERROR("%s", errmsg);
2122 return false;
2123 }
2124 response[nbytes_read - 1] = '\0';
2125 DEBUGF(DBG_FOCUS, "RES (%s)", response);
2126
2127 int HndCtlr;
2128 rc = sscanf(response, "%15[^=]=%d", key, &HndCtlr);
2129 if (rc != 2)
2130 return false;
2131
2132 FocuserStatusLP[STATUS_HNDCTRL].setState( HndCtlr ? IPS_OK : IPS_IDLE);
2133
2134 FocuserStatusLP.setState(IPS_OK);
2135 FocuserStatusLP.apply();
2136
2137 // Added By Philippe Besson the 28th of June for 'END' evaluation
2138 // END is reached
2139 memset(response, 0, sizeof(response));
2140 if (isSimulation())
2141 {
2142 strncpy(response, "END\n", 16);
2143 nbytes_read = strlen(response);
2144 }
2145 else if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2146 {
2147 tty_error_msg(errcode, errmsg, MAXRBUF);
2148 LOGF_ERROR("%s", errmsg);
2149 return false;
2150 }
2151
2152 if (nbytes_read > 0)
2153 {
2154 response[nbytes_read - 1] = '\0';
2155
2156 // Display the response to be sure to have read the complete TTY Buffer.
2157 LOGF_DEBUG("RES (%s)", response);
2158
2159 if (strcmp(response, "END"))
2160 {
2161 LOG_WARN("Invalid END response.");
2162 return false;
2163 }
2164 }
2165 // End of added code by Philippe Besson
2166
2167 tcflush(PortFD, TCIFLUSH);
2168
2169 return true;
2170
2171}
2172
2173/************************************************************************************
2174 *
2175* ***********************************************************************************/
2176bool Gemini::setLedLevel(int level)
2177// Write via the serial port to the HUB the selected LED intensity level
2178
2179{
2180 char cmd[16];
2181 int errcode = 0;
2182 char errmsg[MAXRBUF];
2183 char response[16];
2184 int nbytes_read = 0;
2185 int nbytes_written = 0;
2186
2187 memset(response, 0, sizeof(response));
2188
2189 snprintf(cmd, 16, "<H100SETLED%d>", level);
2190
2191 LOGF_DEBUG("CMD (%s)", cmd);
2192
2193 if (isSimulation())
2194 {
2195 strncpy(response, "SET", 16);
2196 nbytes_read = strlen(response) + 1;
2197 }
2198 else
2199 {
2200 tcflush(PortFD, TCIFLUSH);
2201
2202 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2203 {
2204 tty_error_msg(errcode, errmsg, MAXRBUF);
2205 LOGF_ERROR("%s", errmsg);
2206 return false;
2207 }
2208
2209 if (isResponseOK() == false)
2210 return false;
2211
2212 if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2213 {
2214 tty_error_msg(errcode, errmsg, MAXRBUF);
2215 LOGF_ERROR("%s", errmsg);
2216 return false;
2217 }
2218 }
2219
2220 if (nbytes_read > 0)
2221 {
2222 response[nbytes_read - 1] = '\0';
2223 LOGF_DEBUG("RES (%s)", response);
2224 tcflush(PortFD, TCIFLUSH);
2225
2226 if (!strcmp(response, "SET"))
2227 return true;
2228 else
2229 return false;
2230 }
2231
2232 return false;
2233}
2234
2235/************************************************************************************
2236 *
2237* ***********************************************************************************/
2238bool Gemini::setNickname(DeviceType type, const char *nickname)
2239// Write via the serial port to the HUB the choiced nikname of he focuser
2240{
2241 char cmd[32];
2242 int errcode = 0;
2243 char errmsg[MAXRBUF];
2244 char response[16];
2245 int nbytes_read = 0;
2246 int nbytes_written = 0;
2247
2248 memset(response, 0, sizeof(response));
2249
2250 snprintf(cmd, 32, "<%c100SETDNN%s>", (type == DEVICE_FOCUSER ? 'F' : 'R'), nickname);
2251
2252 LOGF_DEBUG("CMD (%s)", cmd);
2253
2254 if (!isSimulation())
2255 {
2256 tcflush(PortFD, TCIFLUSH);
2257
2258 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2259 {
2260 tty_error_msg(errcode, errmsg, MAXRBUF);
2261 LOGF_ERROR("%s", errmsg);
2262 return false;
2263 }
2264
2265 if (isResponseOK() == false)
2266 return false;
2267
2268 // Read the 'END'
2269 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2270 }
2271
2272 tcflush(PortFD, TCIFLUSH);
2273 return true;
2274}
2275
2276/************************************************************************************
2277 *
2278* ***********************************************************************************/
2279bool Gemini::halt(DeviceType type)
2280{
2281 char cmd[32];
2282 int errcode = 0;
2283 char errmsg[MAXRBUF];
2284 char response[16];
2285 int nbytes_read = 0;
2286 int nbytes_written = 0;
2287
2288 memset(response, 0, sizeof(response));
2289
2290 snprintf(cmd, 32, "<%c100DOHALT>", (type == DEVICE_FOCUSER ? 'F' : 'R'));
2291 LOGF_DEBUG("CMD (%s)", cmd);
2292
2293 if (isSimulation())
2294 {
2295 if (type == DEVICE_FOCUSER)
2296 focuserSimStatus[STATUS_MOVING] = ISS_OFF;
2297 else
2298 {
2299 rotatorSimStatus[STATUS_MOVING] = ISS_OFF;
2300 isRotatorHoming = false;
2301 }
2302 }
2303 else
2304 {
2305 tcflush(PortFD, TCIFLUSH);
2306
2307 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2308 {
2309 tty_error_msg(errcode, errmsg, MAXRBUF);
2310 LOGF_ERROR("%s", errmsg);
2311 return false;
2312 }
2313
2314 if (isResponseOK() == false)
2315 return false;
2316
2317 // Read the 'END'
2318 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2319 }
2320
2321 isRotatorHoming = false;
2322
2323 tcflush(PortFD, TCIFLUSH);
2324
2325 return true;
2326}
2327
2328/************************************************************************************
2329 *
2330* ***********************************************************************************/
2331bool Gemini::home(DeviceType type)
2332{
2333 char cmd[32];
2334 int errcode = 0;
2335 char errmsg[MAXRBUF];
2336 char response[16];
2337 int nbytes_read = 0;
2338 int nbytes_written = 0;
2339
2340 memset(response, 0, sizeof(response));
2341
2342 snprintf(cmd, 32, "<%c100DOHOME>", (type == DEVICE_FOCUSER ? 'F' : 'R'));
2343 LOGF_DEBUG("CMD (%s)", cmd);
2344
2345 if (isSimulation())
2346 {
2347 if (type == DEVICE_FOCUSER)
2348 {
2349 focuserSimStatus[STATUS_HOMING] = ISS_ON;
2350 targetFocuserPosition = 0;
2351 }
2352 else
2353 {
2354 rotatorSimStatus[STATUS_HOMING] = ISS_ON;
2355 targetRotatorPosition = 0;
2356 }
2357 }
2358 else
2359 {
2360 tcflush(PortFD, TCIFLUSH);
2361
2362 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2363 {
2364 tty_error_msg(errcode, errmsg, MAXRBUF);
2365 LOGF_ERROR("%s", errmsg);
2366 return false;
2367 }
2368
2369 if (isResponseOK() == false)
2370 return false;
2371
2372 // Read the 'END'
2373 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2374 }
2375
2376 tcflush(PortFD, TCIFLUSH);
2377
2378 return true;
2379}
2380
2381/************************************************************************************
2382 *
2383* ***********************************************************************************/
2384bool Gemini::homeOnStart(DeviceType type, bool enable)
2385{
2386 char cmd[32];
2387 int errcode = 0;
2388 char errmsg[MAXRBUF];
2389 char response[16];
2390 int nbytes_read = 0;
2391 int nbytes_written = 0;
2392
2393 memset(response, 0, sizeof(response));
2394
2395 snprintf(cmd, 32, "<%c100SETHOS%d>", (type == DEVICE_FOCUSER ? 'F' : 'R'), enable ? 1 : 0);
2396 LOGF_DEBUG("CMD (%s)", cmd);
2397
2398 if (isSimulation() == false)
2399 {
2400 tcflush(PortFD, TCIFLUSH);
2401
2402 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2403 {
2404 tty_error_msg(errcode, errmsg, MAXRBUF);
2405 LOGF_ERROR("%s", errmsg);
2406 return false;
2407 }
2408
2409 if (isResponseOK() == false)
2410 return false;
2411
2412 // Read the 'END'
2413 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2414 }
2415
2416 tcflush(PortFD, TCIFLUSH);
2417
2418 return true;
2419}
2420
2421/************************************************************************************
2422 *
2423* ***********************************************************************************/
2424bool Gemini::center(DeviceType type)
2425{
2426 if (type == DEVICE_ROTATOR)
2427 return MoveAbsRotatorTicks(RotatorAbsPosNP[0].getMax() / 2);
2428
2429 const char * cmd = "<F100CENTER>";
2430 int errcode = 0;
2431 char errmsg[MAXRBUF];
2432 char response[16];
2433 int nbytes_read = 0;
2434 int nbytes_written = 0;
2435
2436 memset(response, 0, sizeof(response));
2437
2438 LOGF_DEBUG("CMD (%s)", cmd);
2439
2440 if (isSimulation())
2441 {
2442 if (type == DEVICE_FOCUSER)
2443 {
2444 focuserSimStatus[STATUS_MOVING] = ISS_ON;
2445 targetFocuserPosition = FocusAbsPosNP[0].getMax() / 2;
2446 }
2447 else
2448 {
2449 rotatorSimStatus[STATUS_MOVING] = ISS_ON;
2450 targetRotatorPosition = RotatorAbsPosNP[0].getMax() / 2;
2451 }
2452
2453 }
2454 else
2455 {
2456 tcflush(PortFD, TCIFLUSH);
2457
2458 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2459 {
2460 tty_error_msg(errcode, errmsg, MAXRBUF);
2461 LOGF_ERROR("%s", errmsg);
2462 return false;
2463 }
2464
2465 if (isResponseOK() == false)
2466 return false;
2467
2468 // Read the 'END'
2469 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2470 }
2471
2472 tcflush(PortFD, TCIFLUSH);
2473
2474 return true;
2475}
2476
2477/************************************************************************************
2478 *
2479* ***********************************************************************************/
2480bool Gemini::setTemperatureCompensation(bool enable)
2481{
2482 char cmd[16];
2483 int errcode = 0;
2484 char errmsg[MAXRBUF];
2485 char response[16];
2486 int nbytes_read = 0;
2487 int nbytes_written = 0;
2488
2489 memset(response, 0, sizeof(response));
2490
2491 snprintf(cmd, 16, "<F100SETTCE%d>", enable ? 1 : 0);
2492
2493 LOGF_DEBUG("CMD (%s)", cmd);
2494
2495 if (isSimulation() == false)
2496 {
2497 tcflush(PortFD, TCIFLUSH);
2498
2499 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2500 {
2501 tty_error_msg(errcode, errmsg, MAXRBUF);
2502 LOGF_ERROR("%s", errmsg);
2503 return false;
2504 }
2505
2506 if (isResponseOK() == false)
2507 return false;
2508
2509 // Read the 'END'
2510 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2511 }
2512
2513 return true;
2514}
2515
2516/************************************************************************************
2517 *
2518* ***********************************************************************************/
2519bool Gemini::setTemperatureCompensationMode(char mode)
2520{
2521 char cmd[16];
2522 int errcode = 0;
2523 char errmsg[MAXRBUF];
2524 char response[16];
2525 int nbytes_read = 0;
2526 int nbytes_written = 0;
2527
2528 memset(response, 0, sizeof(response));
2529
2530 snprintf(cmd, 16, "<F100SETTCM%c>", mode);
2531
2532 LOGF_DEBUG("CMD (%s)", cmd);
2533
2534 if (isSimulation() == false)
2535 {
2536 tcflush(PortFD, TCIFLUSH);
2537
2538 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2539 {
2540 tty_error_msg(errcode, errmsg, MAXRBUF);
2541 LOGF_ERROR("%s", errmsg);
2542 return false;
2543 }
2544
2545 if (isResponseOK() == false)
2546 return false;
2547
2548 // Read the 'END'
2549 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2550 }
2551
2552 return true;
2553}
2554
2555/************************************************************************************
2556 *
2557* ***********************************************************************************/
2558bool Gemini::setTemperatureCompensationCoeff(char mode, int16_t coeff)
2559{
2560 char cmd[32];
2561 int errcode = 0;
2562 char errmsg[MAXRBUF];
2563 char response[16];
2564 int nbytes_read = 0;
2565 int nbytes_written = 0;
2566
2567 memset(response, 0, sizeof(response));
2568
2569 snprintf(cmd, 32, "<F100SETTCC%c%c%04d>", mode, coeff >= 0 ? '+' : '-', (int)std::abs(coeff));
2570
2571 LOGF_DEBUG("CMD (%s)", cmd);
2572
2573 if (isSimulation() == false)
2574 {
2575 tcflush(PortFD, TCIFLUSH);
2576
2577 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2578 {
2579 tty_error_msg(errcode, errmsg, MAXRBUF);
2580 LOGF_ERROR("%s", errmsg);
2581 return false;
2582 }
2583
2584 if (isResponseOK() == false)
2585 return false;
2586
2587 // Read the 'END'
2588 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2589 }
2590
2591 return true;
2592}
2593
2594/************************************************************************************
2595 *
2596* ***********************************************************************************/
2597bool Gemini::setTemperatureCompensationOnStart(bool enable)
2598{
2599 char cmd[16];
2600 int errcode = 0;
2601 char errmsg[MAXRBUF];
2602 char response[16];
2603 int nbytes_read = 0;
2604 int nbytes_written = 0;
2605
2606 memset(response, 0, sizeof(response));
2607
2608 snprintf(cmd, 16, "<F100SETTCS%d>", enable ? 1 : 0);
2609
2610 LOGF_DEBUG("CMD (%s)", cmd);
2611
2612 tcflush(PortFD, TCIFLUSH);
2613
2614 if (isSimulation() == false)
2615 {
2616 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2617 {
2618 tty_error_msg(errcode, errmsg, MAXRBUF);
2619 LOGF_ERROR("%s", errmsg);
2620 return false;
2621 }
2622
2623 if (isResponseOK() == false)
2624 return false;
2625
2626 // Read the 'END'
2627 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2628 }
2629
2630 return true;
2631}
2632
2633/************************************************************************************
2634 *
2635* ***********************************************************************************/
2637{
2638 return setBacklashCompensationSteps(DEVICE_ROTATOR, steps);
2639}
2640
2641/************************************************************************************
2642 *
2643* ***********************************************************************************/
2645{
2646 return setBacklashCompensation(DEVICE_ROTATOR, enabled);
2647}
2648
2649/************************************************************************************
2650 *
2651* ***********************************************************************************/
2652bool Gemini::setBacklashCompensation(DeviceType type, bool enable)
2653{
2654 char cmd[16];
2655 int errcode = 0;
2656 char errmsg[MAXRBUF];
2657 char response[16];
2658 int nbytes_read = 0;
2659 int nbytes_written = 0;
2660
2661 memset(response, 0, sizeof(response));
2662
2663 snprintf(cmd, 16, "<%c100SETBCE%d>", (type == DEVICE_FOCUSER ? 'F' : 'R'), enable ? 1 : 0);
2664
2665 LOGF_DEBUG("CMD (%s)", cmd);
2666
2667 if (isSimulation() == false)
2668 {
2669 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2670 {
2671 tty_error_msg(errcode, errmsg, MAXRBUF);
2672 LOGF_ERROR("%s", errmsg);
2673 return false;
2674 }
2675
2676 if (isResponseOK() == false)
2677 return false;
2678
2679 // Read the 'END'
2680 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2681 }
2682
2683 return true;
2684}
2685
2686/************************************************************************************
2687 *
2688* ***********************************************************************************/
2689bool Gemini::setBacklashCompensationSteps(DeviceType type, uint16_t steps)
2690{
2691 char cmd[16];
2692 int errcode = 0;
2693 char errmsg[MAXRBUF];
2694 char response[16];
2695 int nbytes_read = 0;
2696 int nbytes_written = 0;
2697
2698 memset(response, 0, sizeof(response));
2699
2700 snprintf(cmd, 16, "<%c100SETBCS%02d>", (type == DEVICE_FOCUSER ? 'F' : 'R'), steps);
2701
2702 LOGF_DEBUG("CMD (%s)", cmd);
2703
2704 if (isSimulation() == false)
2705 {
2706 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2707 {
2708 tty_error_msg(errcode, errmsg, MAXRBUF);
2709 LOGF_ERROR("%s", errmsg);
2710 return false;
2711 }
2712
2713 if (isResponseOK() == false)
2714 return false;
2715
2716 // Read the 'END'
2717 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2718 }
2719
2720 return true;
2721}
2722
2723/************************************************************************************
2724 *
2725* ***********************************************************************************/
2726bool Gemini::reverseRotator(bool enable)
2727{
2728 char cmd[16];
2729 int errcode = 0;
2730 char errmsg[MAXRBUF];
2731 char response[16];
2732 int nbytes_read = 0;
2733 int nbytes_written = 0;
2734
2735 memset(response, 0, sizeof(response));
2736
2737 snprintf(cmd, 16, "<R100SETREV%d>", enable ? 1 : 0);
2738
2739 LOGF_DEBUG("CMD (%s)", cmd);
2740
2741 if (isSimulation() == false)
2742 {
2743 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2744 {
2745 tty_error_msg(errcode, errmsg, MAXRBUF);
2746 LOGF_ERROR("%s", errmsg);
2747 return false;
2748 }
2749
2750 if (isResponseOK() == false)
2751 return false;
2752
2753 // Read the 'END'
2754 tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read);
2755 }
2756
2757 return true;
2758}
2759
2760/************************************************************************************
2761 *
2762* ***********************************************************************************/
2763bool Gemini::resetFactory()
2764{
2765 const char *cmd = "<H100RESETH>";
2766 int errcode = 0;
2767 char errmsg[MAXRBUF];
2768 char response[16];
2769 int nbytes_read = 0;
2770 int nbytes_written = 0;
2771
2772 memset(response, 0, sizeof(response));
2773
2774 LOGF_DEBUG("CMD (%s)", cmd);
2775
2776 if (isSimulation())
2777 {
2778 strncpy(response, "SET", 16);
2779 nbytes_read = strlen(response) + 1;
2780 }
2781 else
2782 {
2783 tcflush(PortFD, TCIFLUSH);
2784
2785 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2786 {
2787 tty_error_msg(errcode, errmsg, MAXRBUF);
2788 LOGF_ERROR("%s", errmsg);
2789 return false;
2790 }
2791
2792 if (isResponseOK() == false)
2793 return false;
2794
2795 if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2796 {
2797 tty_error_msg(errcode, errmsg, MAXRBUF);
2798 LOGF_ERROR("%s", errmsg);
2799 return false;
2800 }
2801 }
2802
2803 if (nbytes_read > 0)
2804 {
2805 response[nbytes_read - 1] = '\0';
2806 LOGF_DEBUG("RES (%s)", response);
2807 tcflush(PortFD, TCIFLUSH);
2808
2809 if (!strcmp(response, "SET"))
2810 {
2811 //return true;
2812 getFocusConfig();
2813 getRotatorConfig();
2814 }
2815 else
2816 return false;
2817 }
2818
2819 return false;
2820}
2821
2822/************************************************************************************
2823 *
2824* ***********************************************************************************/
2826{
2827 int errcode = 0;
2828 char errmsg[MAXRBUF];
2829 char response[32];
2830 int nbytes_read = 0;
2831
2832 memset(response, 0, sizeof(response));
2833
2834 if (isSimulation())
2835 {
2836 strcpy(response, "!00");
2837 nbytes_read = strlen(response) + 1;
2838 }
2839 else
2840 {
2841 if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2842 {
2843 tty_error_msg(errcode, errmsg, MAXRBUF);
2844 LOGF_ERROR("TTY error: %s", errmsg);
2845 return false;
2846 }
2847 }
2848
2849 if (nbytes_read > 0)
2850 {
2851 response[nbytes_read - 1] = '\0';
2852 LOGF_DEBUG("RES (%s)", response);
2853
2854 if (!strcmp(response, "!00"))
2855 return true;
2856 else
2857 {
2858 memset(response, 0, sizeof(response));
2859 while (strstr(response, "END") == nullptr)
2860 {
2861 if ((errcode = tty_read_section(PortFD, response, 0xA, GEMINI_TIMEOUT, &nbytes_read)) != TTY_OK)
2862 {
2863 tty_error_msg(errcode, errmsg, MAXRBUF);
2864 LOGF_ERROR("TTY error: %s", errmsg);
2865 return false;
2866 }
2867 response[nbytes_read - 1] = '\0';
2868 LOGF_ERROR("Controller error: %s", response);
2869 }
2870
2871 return false;
2872 }
2873 }
2874 return true;
2875}
2876
2877/************************************************************************************
2878*
2879* ***********************************************************************************/
2880IPState Gemini::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
2881{
2882 char cmd[16];
2883 int errcode = 0;
2884 char errmsg[MAXRBUF];
2885 char response[16];
2886 int nbytes_written = 0;
2887
2888 INDI_UNUSED(speed);
2889
2890 memset(response, 0, sizeof(response));
2891
2892 snprintf(cmd, 16, "<F100DOMOVE%c>", (dir == FOCUS_INWARD) ? '0' : '1');
2893
2894 LOGF_DEBUG("CMD (%s)", cmd);
2895
2896 if (!isSimulation())
2897 {
2898 tcflush(PortFD, TCIFLUSH);
2899
2900 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2901 {
2902 tty_error_msg(errcode, errmsg, MAXRBUF);
2903 LOGF_ERROR("%s", errmsg);
2904 return IPS_ALERT;
2905 }
2906
2907 if (isResponseOK() == false)
2908 return IPS_ALERT;
2909
2910 gettimeofday(&focusMoveStart, nullptr);
2911 focusMoveRequest = duration / 1000.0;
2912 }
2913
2914 if (duration <= getCurrentPollingPeriod())
2915 {
2916 usleep(getCurrentPollingPeriod() * 1000);
2917 AbortFocuser();
2918 return IPS_OK;
2919 }
2920
2921 tcflush(PortFD, TCIFLUSH);
2922
2923 return IPS_BUSY;
2924}
2925
2926/************************************************************************************
2927*
2928* ***********************************************************************************/
2929IPState Gemini::MoveAbsFocuser(uint32_t targetTicks)
2930{
2931 char cmd[32];
2932 int errcode = 0;
2933 char errmsg[MAXRBUF];
2934 char response[16];
2935 int nbytes_written = 0;
2936
2937 targetFocuserPosition = targetTicks;
2938
2939 memset(response, 0, sizeof(response));
2940
2941 snprintf(cmd, 32, "<F100MOVABS%06d>", targetTicks);
2942
2943 LOGF_DEBUG("CMD (%s)", cmd);
2944
2945 if (!isSimulation())
2946 {
2947 tcflush(PortFD, TCIFLUSH);
2948
2949 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
2950 {
2951 tty_error_msg(errcode, errmsg, MAXRBUF);
2952 LOGF_ERROR("%s", errmsg);
2953 return IPS_ALERT;
2954 }
2955
2956 if (isResponseOK() == false)
2957 return IPS_ALERT;
2958 }
2959
2961
2962 tcflush(PortFD, TCIFLUSH);
2963
2964 return IPS_BUSY;
2965}
2966
2967/************************************************************************************
2968*
2969* ***********************************************************************************/
2971{
2972 uint32_t newPosition = 0;
2973
2974 if (dir == FOCUS_INWARD)
2975 newPosition = FocusAbsPosNP[0].getValue() - ticks;
2976 else
2977 newPosition = FocusAbsPosNP[0].getValue() + ticks;
2978
2979 return MoveAbsFocuser(newPosition);
2980}
2981
2982/************************************************************************************
2983*
2984* ***********************************************************************************/
2986{
2987 if (!isConnected())
2988 return;
2989
2991 {
2993 return;
2994 }
2995
2996 // Focuser Status
2997 bool statusrc = false;
2998 for (int i = 0; i < 2; i++)
2999 {
3000 statusrc = getFocusStatus();
3001 if (statusrc)
3002 break;
3003 }
3004
3005 if (statusrc == false)
3006 {
3007 LOG_WARN("Unable to read focuser status....");
3009 return;
3010 }
3011
3013 {
3014 if (isSimulation())
3015 {
3016 if (FocusAbsPosNP[0].getValue() < targetFocuserPosition)
3017 focuserSimPosition += 100;
3018 else
3019 focuserSimPosition -= 100;
3020
3021 focuserSimStatus[STATUS_MOVING] = ISS_ON;
3022
3023 if (std::abs((int64_t)focuserSimPosition - (int64_t)targetFocuserPosition) < 100)
3024 {
3025 FocusAbsPosNP[0].setValue(targetFocuserPosition);
3026 focuserSimPosition = FocusAbsPosNP[0].getValue();
3027 focuserSimStatus[STATUS_MOVING] = ISS_OFF;
3028 FocuserStatusLP[STATUS_MOVING].setState(IPS_IDLE);
3029 if (focuserSimStatus[STATUS_HOMING] == ISS_ON)
3030 {
3031 FocuserStatusLP[STATUS_HOMED].setState(IPS_OK);
3032 focuserSimStatus[STATUS_HOMING] = ISS_OFF;
3033 }
3034 }
3035 }
3036
3037 if (isFocuserHoming && FocuserStatusLP[STATUS_HOMED].getState() == IPS_OK)
3038 {
3039 isFocuserHoming = false;
3040 FocuserGotoSP.setState(IPS_OK);
3041 FocuserGotoSP.reset();
3042 FocuserGotoSP[GOTO_HOME].setState(ISS_ON);
3043 FocuserGotoSP.apply();
3046 LOG_INFO("Focuser reached home position.");
3047 }
3048 else if (FocuserStatusLP[STATUS_MOVING].getState() == IPS_IDLE)
3049 {
3054 if (FocuserGotoSP.getState() == IPS_BUSY)
3055 {
3056 FocuserGotoSP.reset();
3057 FocuserGotoSP.setState(IPS_OK);
3058 FocuserGotoSP.apply();
3059 }
3060 LOG_INFO("Focuser reached requested position.");
3061 }
3062 }
3063 if (FocuserStatusLP[STATUS_HOMING].getState() == IPS_BUSY && FocuserGotoSP.getState() != IPS_BUSY)
3064 {
3065 FocuserGotoSP.setState(IPS_BUSY);
3066 FocuserGotoSP.apply();
3067 }
3068
3069 // Rotator Status
3070 statusrc = false;
3071 for (int i = 0; i < 2; i++)
3072 {
3073 statusrc = getRotatorStatus();
3074 if (statusrc)
3075 break;
3076 }
3077
3078 if (statusrc == false)
3079 {
3080 LOG_WARN("Unable to read rotator status....");
3082 return;
3083 }
3084
3085 if (RotatorAbsPosNP.getState() == IPS_BUSY || GotoRotatorNP.getState() == IPS_BUSY)
3086 {
3087 /*if (isSimulation())
3088 {
3089 if (RotatorAbsPosN[0].value < targetRotatorPosition)
3090 RotatorSimPosition += 100;
3091 else
3092 RotatorSimPosition -= 100;
3093
3094 RotatorSimStatus[STATUS_MOVING] = ISS_ON;
3095
3096 if (std::abs((int64_t)RotatorSimPosition - (int64_t)targetRotatorPosition) < 100)
3097 {
3098 RotatorAbsPosN[0].value = targetRotatorPosition;
3099 RotatorSimPosition = RotatorAbsPosN[0].value;
3100 RotatorSimStatus[STATUS_MOVING] = ISS_OFF;
3101 RotatorStatusL[STATUS_MOVING].setState(IPS_IDLE);
3102 if (RotatorSimStatus[STATUS_HOMING] == ISS_ON)
3103 {
3104 RotatorStatusL[STATUS_HOMED].setState(IPS_OK);
3105 RotatorSimStatus[STATUS_HOMING] = ISS_OFF;
3106 }
3107 }
3108 }*/
3109
3110 if (isRotatorHoming && RotatorStatusLP[STATUS_HOMED].getState() == IPS_OK)
3111 {
3112 isRotatorHoming = false;
3116 RotatorAbsPosNP.setState(IPS_OK);
3117 RotatorAbsPosNP.apply();
3120 LOG_INFO("Rotator reached home position.");
3121 }
3122 else if (RotatorStatusLP[STATUS_MOVING].getState() == IPS_IDLE)
3123 {
3124 RotatorAbsPosNP.setState(IPS_OK);
3125 RotatorAbsPosNP.apply();
3129 {
3133 }
3134 LOG_INFO("Rotator reached requested position.");
3135 }
3136 }
3137 if (RotatorStatusLP[STATUS_HOMING].getState() == IPS_BUSY && HomeRotatorSP.getState() != IPS_BUSY)
3138 {
3141 }
3142
3144}
3145
3146/************************************************************************************
3147 *
3148* ***********************************************************************************/
3150{
3151 const char *cmd = "<F100DOHALT>";
3152 int errcode = 0;
3153 char errmsg[MAXRBUF];
3154 char response[16];
3155 int nbytes_written = 0;
3156
3157 memset(response, 0, sizeof(response));
3158
3159 LOGF_DEBUG("CMD (%s)", cmd);
3160
3161 if (isSimulation())
3162 {
3163 strncpy(response, "!00", 16);
3164 focuserSimStatus[STATUS_MOVING] = ISS_OFF;
3165 focuserSimStatus[STATUS_HOMING] = ISS_OFF;
3166 }
3167 else
3168 {
3169 tcflush(PortFD, TCIFLUSH);
3170
3171 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
3172 {
3173 tty_error_msg(errcode, errmsg, MAXRBUF);
3174 LOGF_ERROR("%s", errmsg);
3175 return false;
3176 }
3177
3178 if (isResponseOK() == false)
3179 return false;
3180 }
3181
3182
3184 {
3187 }
3188
3191 FocuserGotoSP.setState(IPS_IDLE);
3192 FocuserGotoSP.reset();
3194 FocuserGotoSP.apply();
3195
3196 tcflush(PortFD, TCIFLUSH);
3197
3198 return true;
3199}
3200
3201/************************************************************************************
3202 *
3203* ***********************************************************************************/
3204float Gemini::calcTimeLeft(timeval start, float req)
3205{
3206 double timesince;
3207 double timeleft;
3208 struct timeval now
3209 {
3210 0, 0
3211 };
3212 gettimeofday(&now, nullptr);
3213
3214 timesince =
3215 (double)(now.tv_sec * 1000.0 + now.tv_usec / 1000) - (double)(start.tv_sec * 1000.0 + start.tv_usec / 1000);
3216 timesince = timesince / 1000;
3217 timeleft = req - timesince;
3218 return timeleft;
3219}
3220
3221/************************************************************************************
3222*
3223* ***********************************************************************************/
3224IPState Gemini::MoveAbsRotatorTicks(uint32_t targetTicks)
3225{
3226 char cmd[32];
3227 int errcode = 0;
3228 char errmsg[MAXRBUF];
3229 char response[16];
3230 int nbytes_written = 0;
3231
3232 targetRotatorPosition = targetTicks;
3233
3234 memset(response, 0, sizeof(response));
3235
3236 snprintf(cmd, 32, "<R100MOVABS%06d>", targetTicks);
3237
3238 LOGF_DEBUG("CMD (%s)", cmd);
3239
3240 if (!isSimulation())
3241 {
3242 tcflush(PortFD, TCIFLUSH);
3243
3244 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
3245 {
3246 tty_error_msg(errcode, errmsg, MAXRBUF);
3247 LOGF_ERROR("%s", errmsg);
3248 return IPS_ALERT;
3249 }
3250
3251 if (isResponseOK() == false)
3252 return IPS_ALERT;
3253 }
3254
3255 RotatorAbsPosNP.setState(IPS_BUSY);
3256
3257 tcflush(PortFD, TCIFLUSH);
3258
3259 return IPS_BUSY;
3260}
3261
3262/************************************************************************************
3263*
3264* ***********************************************************************************/
3265IPState Gemini::MoveAbsRotatorAngle(double angle)
3266{
3267 char cmd[32];
3268 char response[16];
3269 int nbytes_written = 0;
3270
3271 targetRotatorAngle = angle * 1000.0;
3272
3273 memset(response, 0, sizeof(response));
3274
3275 snprintf(cmd, 32, "<R100MOVEPA%06ud>", targetRotatorAngle);
3276
3277 LOGF_DEBUG("CMD (%s)", cmd);
3278
3279 if (!isSimulation())
3280 {
3281 int errcode = 0;
3282 char errmsg[MAXRBUF];
3283 tcflush(PortFD, TCIFLUSH);
3284
3285 if ((errcode = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
3286 {
3287 tty_error_msg(errcode, errmsg, MAXRBUF);
3288 LOGF_ERROR("%s", errmsg);
3289 return IPS_ALERT;
3290 }
3291
3292 if (isResponseOK() == false)
3293 return IPS_ALERT;
3294 }
3295
3297
3298 tcflush(PortFD, TCIFLUSH);
3299
3300 return IPS_BUSY;
3301}
3302
3303/************************************************************************************
3304 *
3305* ***********************************************************************************/
3307{
3308 // Save Focuser configs
3310 // Rotator Configs
3312
3313 TemperatureCompensateSP.save(fp);
3314 TemperatureCompensateOnStartSP.save(fp);
3315 TemperatureCoeffNP.save(fp);
3316 TemperatureCompensateModeSP.save(fp);
3317 FocuserHomeOnStartSP.apply();
3318 RotatorHomeOnStartSP.save(fp);
3319
3320 return true;
3321}
3322
3323/************************************************************************************
3324 *
3325* ***********************************************************************************/
3327{
3328 IPState state = MoveAbsRotatorAngle(angle);
3329 RotatorAbsPosNP.setState(state);
3330 RotatorAbsPosNP.apply();
3331
3332 return state;
3333}
3334
3335/************************************************************************************
3336 *
3337* ***********************************************************************************/
3339{
3340 return (home(DEVICE_ROTATOR) ? IPS_BUSY : IPS_ALERT);
3341}
3342
3343/************************************************************************************
3344 *
3345* ***********************************************************************************/
3346bool Gemini::ReverseRotator(bool enabled)
3347{
3348 return reverseRotator(enabled);
3349}
3350
3351/************************************************************************************
3352 *
3353* ***********************************************************************************/
3355{
3356 return setBacklashCompensationSteps(DEVICE_FOCUSER, steps);
3357}
3358
3359/************************************************************************************
3360 *
3361* ***********************************************************************************/
3363{
3364 return setBacklashCompensation(DEVICE_FOCUSER, enabled);
3365}
double temperature
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
@ FOCUS_C_COEFF
Definition gemini.h:39
@ FOCUS_B_COEFF
Definition gemini.h:38
@ FOCUS_A_COEFF
Definition gemini.h:37
@ FOCUS_D_COEFF
Definition gemini.h:40
@ FOCUS_E_COEFF
Definition gemini.h:41
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition gemini.cpp:2985
virtual bool saveConfigItems(FILE *fp) override
Definition gemini.cpp:3306
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition gemini.cpp:2970
~Gemini()
Definition gemini.cpp:76
bool isResponseOK()
Definition gemini.cpp:2825
virtual IPState HomeRotator() override
HomeRotator Go to home position.
Definition gemini.cpp:3338
Gemini()
Definition gemini.cpp:47
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser the focuser in a particular direction with a specific speed for a finite duration.
Definition gemini.cpp:2880
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Processes incoming new text values from the client for this device. Delegates processing to the contr...
Definition gemini.cpp:606
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
Definition gemini.cpp:3362
@ GOTO_HOME
Definition gemini.h:59
@ GOTO_CENTER
Definition gemini.h:58
bool focuserConfigurationComplete
Definition gemini.h:97
bool ack()
Definition gemini.cpp:743
virtual IPState MoveRotator(double angle) override
MoveRotator Go to specific angle.
Definition gemini.cpp:3326
bool rotatorConfigurationComplete
Definition gemini.h:98
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
Definition gemini.cpp:629
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
Definition gemini.cpp:239
virtual bool SetRotatorBacklashEnabled(bool enabled) override
SetRotatorBacklashEnabled Enables or disables the Rotator backlash compensation.
Definition gemini.cpp:2644
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition gemini.cpp:3149
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
Definition gemini.cpp:3354
@ DEVICE_ROTATOR
Definition gemini.h:64
@ DEVICE_FOCUSER
Definition gemini.h:63
virtual bool ReverseRotator(bool enabled) override
ReverseRotator Reverse the direction of the rotator. CW is usually the normal direction,...
Definition gemini.cpp:3346
virtual IPState MoveAbsFocuser(uint32_t targetPosition) override
MoveFocuser the focuser to an absolute position.
Definition gemini.cpp:2929
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
Definition gemini.cpp:348
@ STATUS_TMPPROBE
Definition gemini.h:50
@ STATUS_REVERSE
Definition gemini.h:53
@ STATUS_REMOTEIO
Definition gemini.h:51
@ STATUS_HOMING
Definition gemini.h:47
@ STATUS_HOMED
Definition gemini.h:48
@ STATUS_FFDETECT
Definition gemini.h:49
@ STATUS_HNDCTRL
Definition gemini.h:52
@ STATUS_MOVING
Definition gemini.h:46
virtual bool SetRotatorBacklash(int32_t steps) override
SetRotatorBacklash Set the Rotatorer backlash compensation value.
Definition gemini.cpp:2636
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
Definition gemini.cpp:323
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
Definition gemini.cpp:83
virtual const char * getDefaultName() override
Definition gemini.cpp:339
bool isConnected() const
INDI::PropertyText getText(const char *name) const
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
uint32_t getDriverInterface() const
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusTimerNP
INDI::PropertySwitch FocusBacklashSP
INDI::PropertyNumber FocusBacklashNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
Connection::Serial * serialConnection
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Processes incoming new text values from the client for this device. Delegates processing to the contr...
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void setName(const char *name)
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
void fill(const char *device, const char *name, const char *label, const char *group, IPState state)
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
INDI::PropertySwitch AbortRotatorSP
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process Rotator switch properties.
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
INDI::PropertySwitch RotatorBacklashSP
void initProperties(const char *groupName)
Initialize Rotator properties. It is recommended to call this function within initProperties() of you...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
INDI::PropertyNumber RotatorBacklashNP
INDI::PropertySwitch HomeRotatorSP
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process Rotator number properties.
INDI::PropertySwitch ReverseRotatorSP
INDI::PropertyNumber GotoRotatorNP
Provides interface to implement Rotator functionality.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
#define FOCUS_SETTINGS_TAB
Definition dmfc.cpp:34
#define ROTATOR_TAB
Definition gemini.cpp:39
#define HUB_TAB
Definition gemini.cpp:40
#define GEMINI_TIMEOUT
Definition gemini.cpp:32
#define STATUS_TAB
Definition gemini.cpp:38
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_ATMOST1
Definition indiapi.h:172
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:653
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:490
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition indidevapi.c:376
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition indidevapi.c:398
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:453
#define INDI_UNUSED(x)
Definition indidevapi.h:132
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#define MAXRBUF
Definition indidriver.c:52
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_WARN(txt)
Definition indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define LOG_INFO(txt)
Definition indilogger.h:74
#define DEBUGF(priority, msg,...)
Definition indilogger.h:57
#define getDeviceName
uint16_t type
Definition pwc-ioctl.h:0
uint8_t cmd[4]
Definition pwc-ioctl.h:2
static Logger & getInstance()
Method to get a reference to the object (i.e., Singleton) It is a static method.
int addDebugLevel(const char *debugLevelName, const char *LoggingLevelName)
Adds a new debugging level to the driver.