Instrument Neutral Distributed Interface INDI 2.2.5
teenastro.cpp
Go to the documentation of this file.
1/*
2 TeenAstro Focuser
3 Copyright (C) 2021 Markus Noga
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
21#include "teenastro.h"
22#include "indicom.h"
23#include "indicontroller.h"
24
25#include <unistd.h> // for sleep()
26#include <termios.h> // for tcflush
27
28// Default, minimal and maximal values for focuser configuration properties
29// In absolute units (not device units, where e.g. current is /10 and microsteps are log_2)
30//
31
32#define TAF_curr_default 500
33#define TAF_curr_min 100
34#define TAF_curr_max 1600
35#define TAF_micro_default (1<<4)
36#define TAF_micro_min (1<<2)
37#define TAF_micro_max (1<<7)
38#define TAF_steprot_default 200
39#define TAF_steprot_min 10
40#define TAF_steprot_max 800
41#define TAF_pos_default 0
42#define TAF_pos_min 0
43#define TAF_pos_max 2000000000UL
44#define TAF_speed_default 20
45#define TAF_speed_min 1
46#define TAF_speed_max 999
47#define TAF_acc_default 30
48#define TAF_acc_min 1
49#define TAF_acc_max 99
50#define TAF_res_default 16
51#define TAF_res_min 1
52#define TAF_res_max 512
53
54#define TAF_UI_STEPS 100.0
55#define TAF_STEP(min,max) (((max)-(min))/(TAF_UI_STEPS))
56
57
58#define TAF_FOCUSER_TIMEOUT 2
59#define TAF_FOCUSER_BUFSIZE 128
60
61// Focuser singleton
62std::unique_ptr<TeenAstroFocuser> teenAstroFocuser(new TeenAstroFocuser());
63
64// Public methods
65//
66
72
76
78{
79 return "TeenAstroFocuser";
80}
81
83{
84 char resp[TAF_FOCUSER_BUFSIZE];
85
86 // Issue handshake challenge for TeenAstro focuser
87 if(!sendAndReceive(":FV#", resp, TAF_FOCUSER_BUFSIZE))
88 return false;
89 if (strncmp(resp, "$ TeenAstro Focuser ", 20))
90 {
91 DEBUGF(INDI::Logger::DBG_ERROR, "Handshake response: %s", resp);
92 return false;
93 }
94
95 // TeenAstro mounts internally forward focuser commands via a
96 // serial connection. When mount & focuser are both on USB,
97 // and scanning for devices, a race condition can occur. The
98 // focuser device driver may probe the USB connection of the
99 // mount first, and receive a correct response to the focuser
100 // handshake challenge. Then the focuser driver would block
101 // the USB port of the mount. And the scan performed by
102 // mount driver would fail. To avoid this race condition,
103 // we issue the handshake challenge for a LX200 mount and
104 // abort if it is answered.
105 if(!sendAndExpectTimeout(":GR#", resp, TAF_FOCUSER_BUFSIZE))
106 {
107 DEBUGF(INDI::Logger::DBG_DEBUG, "Device responded to focuser and mount handshake (%s), skipping.", resp);
108 return false;
109 }
110
111 DEBUGF(INDI::Logger::DBG_DEBUG, "TeenAstroFocuser %s found", &resp[20]);
112 return true;
113}
114
116{
118
119 FocusSyncNP[0].setLabel("Ticks"); // Rename unit of measure to ticks, to avoid confusion with motor steps,
120 FocusMaxPosNP[0].setLabel("Ticks"); // motor microsteps and the effect of the resolution setting.
121 FocusRelPosNP[0].setLabel("Ticks"); // Ticks are resolution units.
122 FocusAbsPosNP[0].setLabel("Ticks");
123
125
126 FocusSpeedNP[0].setLabel("Go-to speed");
128 FocusSpeedNP[0].setLabel("Steps/s");
129 FocusSpeedNP[0].setMin(TAF_speed_min);
130 FocusSpeedNP[0].setMax(TAF_speed_max);
132
133 // Main control tab
134 //
135
136 CfgParkPosNP[0].fill("VAL", "Ticks", "%.f", 0, 100000, 1000, 0);
137 CfgParkPosNP.fill(getDeviceName(), "PARK_POS", "Park position", MAIN_CONTROL_TAB, IP_RW, 60,
138 IPS_IDLE );
139
140 IUFillSwitch(&GoToParkS[0], "VAL", "Park", ISS_OFF);
141 IUFillSwitchVector(&GoToParkSP, GoToParkS, 1, getDeviceName(), "GOTO_PARK", "Go-to park", MAIN_CONTROL_TAB, IP_RW,
142 ISR_ATMOST1, 60, IPS_IDLE );
143
146 IUFillNumberVector(&CurSpeedNP, CurSpeedN, 1, getDeviceName(), "CUR_SPEED", "Current Speed", MAIN_CONTROL_TAB, IP_RO, 0,
147 IPS_IDLE );
148
149 IUFillNumber(&TempN[0], "VAL", "Celsius", "%+.1f°", -50., 50., 0, 0);
150 IUFillNumberVector(&TempNP, TempN, 1, getDeviceName(), "TEMP", "Temperature", MAIN_CONTROL_TAB, IP_RO, 0, IPS_IDLE );
151
152 // Focuser tab
153 //
154
155 IUFillText(&DeviceVersionT[0], "VAL", "Version", "unknown");
156 IUFillTextVector(&DeviceVersionTP, DeviceVersionT, 1, getDeviceName(), "DEVICE_VERSION", "Device version", FOCUS_TAB, IP_RO,
157 60, IPS_IDLE);
158
159 // Focuser tab: Motor configuration
160 //
161
165 "Steps/rev.", FOCUS_TAB, IP_RW, 60, IPS_IDLE );
166
175
176 CfgMotorResolutionNP[0].fill("VAL", "Microsteps/tick", "%.f", TAF_res_min, TAF_res_max, TAF_STEP(TAF_res_min,
178 CfgMotorResolutionNP.fill(getDeviceName(), "MOT_RES", "Resolution", FOCUS_TAB,
179 IP_RW, 60, IPS_IDLE );
180
183 CfgMotorCurrentNP.fill(getDeviceName(), "MOT_CUR", "Motor current", FOCUS_TAB, IP_RW,
184 60, IPS_IDLE );
185
186 // Focuser tab: Motion configuration
187 //
188
189 CfgGoToAccNP[0].fill("VAL", "Steps/s^2", "%.f", TAF_acc_min, TAF_acc_max, TAF_STEP(TAF_acc_min, TAF_acc_max),
191 CfgGoToAccNP.fill(getDeviceName(), "GOTO_ACCEL", "Go-to accel.", FOCUS_TAB, IP_RW, 60,
192 IPS_IDLE );
193
196 CfgManualSpeedNP.fill(getDeviceName(), "MAN_SPEED", "Manual speed", FOCUS_TAB, IP_RW,
197 60, IPS_IDLE );
198
201 CfgManualAccNP.fill(getDeviceName(), "MAN_ACCEL", "Manual accel.", FOCUS_TAB, IP_RW, 60,
202 IPS_IDLE );
203
206 CfgManualDecNP.fill(getDeviceName(), "MAN_DECEL", "Manual decel.", FOCUS_TAB, IP_RW, 60,
207 IPS_IDLE );
208
209 // Focuser tab: Device actions
210 //
211
212 IUFillSwitch(&RebootDeviceS[0], "VAL", "Reboot", ISS_OFF);
213 IUFillSwitchVector(&RebootDeviceSP, RebootDeviceS, 1, getDeviceName(), "REBOOT_DEVICE", "Reboot device", FOCUS_TAB, IP_RW,
214 ISR_ATMOST1, 60, IPS_IDLE );
215
216 IUFillSwitch(&EraseEEPROMS[0], "VAL", "Erase", ISS_OFF);
217 IUFillSwitchVector(&EraseEEPROMSP, EraseEEPROMS, 1, getDeviceName(), "ERASE_EEPROM", "Erase EEPROM", FOCUS_TAB, IP_RW,
218 ISR_ATMOST1, 60, IPS_IDLE );
219
221
222 return true;
223}
224
226{
227 FocusAbsPosNP[0].setMax(maxPos);
228 FocusRelPosNP[0].setMax(maxPos);
229 FocusSyncNP[0].setMax(maxPos);
230 CfgParkPosNP[0].setMax(maxPos);
231
232 auto step = maxPos / TAF_UI_STEPS;
233 FocusAbsPosNP[0].setStep(step);
234 FocusRelPosNP[0].setStep(step);
235 FocusSyncNP[0].setStep(step);
236 CfgParkPosNP[0].setStep(step);
237}
238
240{
242 return false;
243
244 if (isConnected())
245 {
246 // Update values from device before defining UI controls.
247 // This minimizes flicker as changes to FocuserMaxPosNP
248 // must redraw all positional controls to update their range.
250 return false;
251
254
255 DEBUG(INDI::Logger::DBG_DEBUG, "TeenAstroFocuser ready for use.");
256 }
257 else
258 {
261 }
262
263 return true;
264}
265
284
292
315
333
334bool TeenAstroFocuser::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
335{
336 if(dev == NULL || strcmp(dev, getDeviceName()))
337 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
338
339 if(!strcmp(name, GoToParkSP.name))
340 {
342 IDSetSwitch(&GoToParkSP, NULL);
343 bool res = goToPark();
344 GoToParkS[0].s = ISS_OFF;
345 GoToParkSP.s = res ? IPS_OK : IPS_ALERT;
346 IDSetSwitch(&GoToParkSP, NULL);
347 return res;
348 }
349 else if(!strcmp(name, CfgMotorMicrostepsSP.name))
350 {
351 // parse selected number of usteps from states and labels. Labels are "Vxxx" where xxx is a number
352 uint32_t usteps = 0;
353 for(int i = 0; i < n; i++)
354 if(states[i] == ISS_ON)
355 usteps = atoi(names[i]);
356
357 bool res = setMotorMicrosteps(usteps);
358 if(res)
359 IUUpdateSwitch(&CfgMotorMicrostepsSP, states, names, n);
362 return res;
363 }
364 else if(!strcmp(name, RebootDeviceSP.name))
365 {
368 bool res = rebootDevice();
369 RebootDeviceS[0].s = ISS_OFF;
372 return res;
373 }
374 else if(!strcmp(name, EraseEEPROMSP.name))
375 {
378 bool res = eraseDeviceEEPROM();
379 EraseEEPROMS[0].s = ISS_OFF;
382 return res;
383 }
384 else
385 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
386}
387
388bool TeenAstroFocuser::ISNewNumberHelper(INDI::PropertyNumber &NP, double values[], char *names[], int n, bool res)
389{
390 if(res)
391 NP.update(values, names, n);
392 NP.setState(res ? IPS_OK : IPS_ALERT);
393 NP.apply();
394 return res;
395}
396
397bool TeenAstroFocuser::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
398{
399 if(dev == NULL || strcmp(dev, getDeviceName()))
400 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
401
402 if(FocusSyncNP.isNameMatch(name))
403 {
404 bool res = SyncFocuser((uint32_t) rint(values[0]));
405 return ISNewNumberHelper(FocusSyncNP, values, names, n, res);
406 }
407 else if(CfgParkPosNP.isNameMatch(name))
408 {
409 bool res = setParkPos((uint32_t) rint(values[0]));
410 return ISNewNumberHelper(CfgParkPosNP, values, names, n, res);
411 }
412 else if(FocusMaxPosNP.isNameMatch(name))
413 {
414 uint32_t val = (uint32_t) rint(values[0]);
415 bool res = SetFocuserMaxPosition(val);
416 if(res && FocusMaxPosNP[0].getValue() != val)
417 {
419 deleteMainControlProperties(); // Force redraw of UI controls as IUUpdateMinMax
420 defineMainControlProperties(); // does not reliably update the step size.
421 }
422 return ISNewNumberHelper(FocusMaxPosNP, values, names, n, res);
423 }
424 else if(CfgManualSpeedNP.isNameMatch(name))
425 {
426 bool res = setManualSpeed((uint32_t) rint(values[0]));
427 return ISNewNumberHelper(CfgManualSpeedNP, values, names, n, res);
428 }
429 else if(FocusSpeedNP.isNameMatch(name))
430 {
431 bool res = SetFocuserSpeed(rint(values[0]));
432 return ISNewNumberHelper(FocusSpeedNP, values, names, n, res);
433 }
434 else if(CfgGoToAccNP.isNameMatch(name))
435 {
436 bool res = setGoToAcc((uint32_t) rint(values[0]));
437 return ISNewNumberHelper(CfgGoToAccNP, values, names, n, res);
438 }
439 else if(CfgManualAccNP.isNameMatch(name))
440 {
441 bool res = setManualAcc((uint32_t) rint(values[0]));
442 return ISNewNumberHelper(CfgManualAccNP, values, names, n, res);
443 }
444 else if(CfgManualDecNP.isNameMatch(name))
445 {
446 bool res = setManualDec((uint32_t) rint(values[0]));
447 return ISNewNumberHelper(CfgManualDecNP, values, names, n, res);
448 }
450 {
451 bool res = setMotorStepsPerRevolution((uint32_t) rint(values[0]));
452 return ISNewNumberHelper(CfgMotorStepsPerRevolutionNP, values, names, n, res);
453 }
454 else if(CfgMotorResolutionNP.isNameMatch(name))
455 {
456 bool res = setMotorResolution((uint32_t) rint(values[0]));
457 return ISNewNumberHelper(CfgMotorResolutionNP, values, names, n, res);
458 }
459 else if(CfgMotorCurrentNP.isNameMatch(name))
460 {
461 bool res = setMotorCurrent((uint32_t) rint(values[0]));
462 return ISNewNumberHelper(CfgMotorCurrentNP, values, names, n, res);
463 }
464 else
465 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
466}
467
468
487
489{
490 FocusRelPosNP[0].setValue(ticks);
491
492 uint32_t pos = uint32_t(FocusAbsPosNP[0].getValue());
493 if (dir == FOCUS_INWARD)
494 pos -= ticks;
495 else
496 pos += ticks;
497
498 return MoveAbsFocuser(pos);
499}
500
502{
503 if(!isConnected())
504 return;
505
506 updateState();
508}
509
511{
514
515 if(!stop())
516 {
519 return false;
520 }
523
524 return updateState();
525}
526
527
528// Protected methods
529//
530
531bool TeenAstroFocuser::send(const char *const msg)
532{
533 DEBUGF(INDI::Logger::DBG_DEBUG, "send(\"%s\")", msg);
534
535 tcflush(PortFD, TCIOFLUSH);
536
537 int nbytes_written = 0, rc = -1;
538 if ( (rc = tty_write(PortFD, msg, strlen(msg), &nbytes_written)) != TTY_OK)
539 {
540 char errstr[MAXRBUF];
541 tty_error_msg(rc, errstr, MAXRBUF);
542 DEBUGF(INDI::Logger::DBG_ERROR, "send(\"%s\"): %s.", msg, errstr);
543 return false;
544 }
545 return true;
546}
547
548
549bool TeenAstroFocuser::sendAndReceive(const char *const msg, char *resp, int bufsize)
550{
551 if(!send(msg))
552 return false;
553
554 int nbytes_read = 0;
555 int rc = tty_nread_section(PortFD, resp, bufsize, '#', TAF_FOCUSER_TIMEOUT, &nbytes_read);
556 resp[nbytes_read] = '\0';
557 if(rc != TTY_OK || nbytes_read == 0 || resp[nbytes_read - 1] != '#')
558 {
559 char errstr[MAXRBUF];
560 tty_error_msg(rc, errstr, MAXRBUF);
561 DEBUGF(INDI::Logger::DBG_ERROR, "sendAndReceive(\"%s\") received \"%s\": %s.", msg, resp, errstr);
562 return false;
563 }
564 DEBUGF(INDI::Logger::DBG_DEBUG, "sendAndReceive(\"%s\") received \"%s\".", msg, resp);
565 return true;
566}
567
568bool TeenAstroFocuser::sendAndReceiveBool(const char *const msg)
569{
570 if(!send(msg))
571 return false;
572
573 char resp[2];
574 int nbytes_read = 0;
575 int rc = tty_read(PortFD, resp, 1, TAF_FOCUSER_TIMEOUT, &nbytes_read);
576 resp[nbytes_read] = '\0';
577 if(rc != TTY_OK || resp[0] != '1')
578 {
579 char errstr[MAXRBUF];
580 tty_error_msg(rc, errstr, MAXRBUF);
581 DEBUGF(INDI::Logger::DBG_ERROR, "sendAndReceiveBool(\"%s\") received \"%s\": %s.", msg, resp, errstr);
582 return false;
583 }
584 DEBUGF(INDI::Logger::DBG_DEBUG, "sendAndReceiveBool(\"%s\") received \"%s\".", msg, resp);
585 return resp[0] == '1';
586}
587
588
589bool TeenAstroFocuser::sendAndExpectTimeout(const char *const msg, char *resp, int bufsize)
590{
591 if(!send(msg))
592 return false;
593
594 int nbytes_read = 0;
595 int rc = tty_nread_section(PortFD, resp, bufsize, '#', TAF_FOCUSER_TIMEOUT, &nbytes_read);
596 resp[nbytes_read] = '\0';
597 if(rc != TTY_TIME_OUT || nbytes_read != 0)
598 {
599 char errstr[MAXRBUF];
600 tty_error_msg(rc, errstr, MAXRBUF);
601 DEBUGF(INDI::Logger::DBG_ERROR, "sendAndExpectTimeout(\"%s\") received \"%s\".", msg, resp);
602 return false;
603 }
604 DEBUGF(INDI::Logger::DBG_DEBUG, "sendAndExpectTimeout(\"%s\") got timeout.", msg, resp);
605 return true;
606}
607
608
610{
611 char resp[TAF_FOCUSER_BUFSIZE];
612 if(!sendAndReceive(":FV#", resp, TAF_FOCUSER_BUFSIZE))
613 return false;
614 int len = strlen(resp);
615 resp[len - 1] = 0;
616 IUSaveText(&DeviceVersionT[0], resp + 2);
619 return true;
620}
621
623{
624 char resp[TAF_FOCUSER_BUFSIZE];
625 int pos = -1, speed = -1;
626 float temp = -1;
627
628 if(!sendAndReceive(":F?#", resp, TAF_FOCUSER_BUFSIZE))
629 return false;
630
631 if(sscanf(resp, "?%d %d %f#", &pos, &speed, &temp) <= 0)
632 {
633 DEBUGF(INDI::Logger::DBG_ERROR, "Invalid format: focuser state (%s)", resp);
634 return false;
635 }
636
637 if(FocusAbsPosNP.getState() == IPS_BUSY && speed == 0)
638 DEBUG(INDI::Logger::DBG_SESSION, "Focuser reached target position.");
639
640 FocusAbsPosNP[0].setValue(pos);
641 FocusAbsPosNP.setState(speed > 0 ? IPS_BUSY : IPS_OK);
643
644 FocusRelPosNP.setState(speed > 0 ? IPS_BUSY : IPS_OK);
646
647 CurSpeedN[0].value = speed;
648 CurSpeedNP.s = speed > 0 ? IPS_BUSY : IPS_OK;
649 IDSetNumber(&CurSpeedNP, NULL);
650
651 TempN[0].value = temp;
652 TempNP.s = (temp == -99) ? IPS_ALERT : IPS_OK;
653 IDSetNumber(&TempNP, NULL);
654
655 return true;
656}
657
659{
660 if(!updateState())
661 return false;
662 return CurSpeedN[0].value > 0;
663}
664
665
667{
668 char resp[TAF_FOCUSER_BUFSIZE];
669 int parkPos = -1, maxPos = -1, manualSpeed = -1, goToSpeed = -1, gotoAcc = -1, manAcc = -1, manDec = -1;
670
671 if(!sendAndReceive(":F~#", resp, TAF_FOCUSER_BUFSIZE))
672 return false;
673
674 if(sscanf(resp, "~%d %d %d %d %d %d %d#", &parkPos, &maxPos, &manualSpeed, &goToSpeed, &gotoAcc, &manAcc, &manDec) <= 0)
675 {
676 DEBUGF(INDI::Logger::DBG_ERROR, "Invalid format: focuser motion config (%s)", resp);
677 return false;
678 }
679
680 if(maxPos != FocusMaxPosNP[0].getValue())
682
683 CfgParkPosNP[0].setValue(parkPos);
686 FocusMaxPosNP[0].setValue(maxPos);
689 CfgManualSpeedNP[0].setValue(manualSpeed);
692 FocusSpeedNP[0].setValue(goToSpeed);
695 CfgGoToAccNP[0].setValue(gotoAcc);
698 CfgManualAccNP[0].setValue(manAcc);
701 CfgManualDecNP[0].setValue(manDec);
704
705 return true;
706}
707
708bool TeenAstroFocuser::setConfigItem(char item, uint32_t deviceValue)
709{
710 char cmd[64];
711 snprintf(cmd, 64, ":F%c,%d#", item, deviceValue);
712 return sendAndReceiveBool(cmd);
713}
714
716{
717 return setConfigItem('0', value);
718}
719
721{
722 return setConfigItem('1', value);
723}
724
726{
727 return setConfigItem('2', value);
728}
729
731{
732 return setConfigItem('3', (uint32_t) value);
733}
734
736{
737 return setConfigItem('4', value);
738}
739
741{
742 return setConfigItem('5', value);
743}
744
746{
747 return setConfigItem('6', value);
748}
749
750
752{
753 char resp[TAF_FOCUSER_BUFSIZE];
754 int reverse = -1, log2_micro = -1, resolution = -1, curr_10ma = -1, steprot = -1;
755
756 if(!sendAndReceive(":FM#", resp, TAF_FOCUSER_BUFSIZE))
757 return false;
758
759 if(sscanf(resp, "M%d %d %d %d %d#", &reverse, &log2_micro, &resolution, &curr_10ma, &steprot) <= 0)
760 {
761 DEBUGF(INDI::Logger::DBG_ERROR, "Invalid format: focuser motor config (%s)", resp);
762 return false;
763 }
764
769
770 uint32_t micro = (1 << log2_micro); // TeenAstro device returns and expects log_2(microsteps)
771 bool microFound = false;
772 for(int i = 0; i < TAF_MICROS_N; i++)
773 {
774 uint32_t thisMicro = (uint32_t) atoi(CfgMotorMicrostepsS[i].name);
775 CfgMotorMicrostepsS[i].s = (micro == thisMicro) ? ISS_ON : ISS_OFF;
776 if(micro == thisMicro)
777 microFound = true;
778 }
779 CfgMotorMicrostepsSP.s = microFound ? IPS_OK : IPS_ALERT;
781
782 CfgMotorResolutionNP[0].setValue(resolution);
785 CfgMotorCurrentNP[0].setValue(curr_10ma * 10); // TeenAstro device returns and expects units of 10 mA
788 CfgMotorStepsPerRevolutionNP[0].setValue(steprot);
791
792 return true;
793}
794
796{
797 return setConfigItem('7', enable ? 1 : 0);
798}
799
801{
802 uint32_t bitPos = 0;
803 value >>= 1;
804 for(; value != 0; bitPos++)
805 value >>= 1;
806 return setConfigItem('m', bitPos); // TeenAstro device returns and expects log_2(microsteps)
807}
808
810{
811 return setConfigItem('8', value);
812}
813
815{
816 return setConfigItem('c', value / 10); // TeenAstro device returns and expects units of 10 mA
817}
818
820{
821 return setConfigItem('r', value);
822}
823
825{
826 char cmd[64];
827 snprintf(cmd, 64, ":FS,%d#", value);
828 return send(cmd); // no confirmation via "0" or "1"
829}
830
831
832bool TeenAstroFocuser::goTo(uint32_t position)
833{
834 char cmd[64];
835 snprintf(cmd, 64, ":FG,%d#", position);
836 return send(cmd);
837}
838
840{
841 return send(":FP#");
842}
843
845{
846 return send(":FQ#");
847}
848
850{
851 if(!send(":F!#"))
852 return false;
853 sleep(3);
855}
856
858{
859 if(!send(":F$#"))
860 return false;
861 sleep(1);
863}
864
866{
867 // This is a verbatim copy of Focuser::saveConfigItems except one override
868 //
869
870 DefaultDevice::saveConfigItems(fp);
871
872 // Do not save focuser configuration items on INDI host, as they are stored on the focuser device.
873 // FI::saveConfigItems(fp);
874
875 PresetNP.save(fp);
876 this->controller->saveConfigItems(fp);
877
878 return true;
879}
bool isConnected() const
virtual bool saveConfigItems(FILE *fp)
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSyncNP
INDI::PropertyNumber FocusSpeedNP
INDI::PropertySwitch FocusAbortSP
INDI::PropertyNumber FocusMaxPosNP
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 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...
Controller * controller
INDI::PropertyNumber PresetNP
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
void setLabel(const char *label)
bool isNameMatch(const char *otherName) const
void setGroupName(const char *name)
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)
ISwitchVectorProperty RebootDeviceSP
Definition teenastro.h:196
bool setManualSpeed(uint32_t value)
void deleteOtherProperties()
ISwitchVectorProperty CfgMotorMicrostepsSP
Definition teenastro.h:183
bool setMotorCurrent(uint32_t value)
bool setManualAcc(uint32_t value)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
bool sendAndReceiveBool(const char *const msg)
INDI::PropertyNumber CfgMotorCurrentNP
Definition teenastro.h:189
bool setConfigItem(char item, uint32_t deviceValue)
void deleteMainControlProperties()
void defineOtherProperties()
virtual bool AbortFocuser()
AbortFocuser all focus motion.
virtual void TimerHit()
Callback function to be called once SetTimer duration elapses.
bool saveConfigItems(FILE *fp)
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
bool setMotorStepsPerRevolution(uint32_t value)
INDI::PropertyNumber CfgManualSpeedNP
Definition teenastro.h:159
bool send(const char *const msg)
INumberVectorProperty TempNP
Definition teenastro.h:144
INDI::PropertyNumber CfgMotorResolutionNP
Definition teenastro.h:186
void initPositionPropertiesRanges(uint32_t maxPos)
bool ReverseFocuser(bool enable)
ReverseFocuser Reverse focuser motion direction.
virtual bool SyncFocuser(uint32_t value)
SyncFocuser Set current position to ticks without moving the focuser.
void defineMainControlProperties()
bool updateMotorConfig()
INumber TempN[1]
Definition teenastro.h:143
bool eraseDeviceEEPROM()
INDI::PropertyNumber CfgManualAccNP
Definition teenastro.h:166
bool setMotorMicrosteps(uint32_t value)
bool setMotorResolution(uint32_t value)
ITextVectorProperty DeviceVersionTP
Definition teenastro.h:154
INDI::PropertyNumber CfgManualDecNP
Definition teenastro.h:169
ISwitchVectorProperty GoToParkSP
Definition teenastro.h:133
ISwitch RebootDeviceS[1]
Definition teenastro.h:195
const char * getDefaultName()
Definition teenastro.cpp:77
bool SetFocuserMaxPosition(uint32_t value)
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
INumber CurSpeedN[1]
Definition teenastro.h:139
bool sendAndReceive(const char *const msg, char *resp, int bufsize)
ISwitchVectorProperty EraseEEPROMSP
Definition teenastro.h:200
bool updateDeviceVersion()
ISwitch GoToParkS[1]
Definition teenastro.h:132
bool sendAndExpectTimeout(const char *const msg, char *resp, int bufsize)
ISwitch CfgMotorMicrostepsS[TAF_MICROS_N]
Definition teenastro.h:182
IText DeviceVersionT[1]
Definition teenastro.h:153
INDI::PropertyNumber CfgGoToAccNP
Definition teenastro.h:162
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks)
MoveFocuser the focuser to an relative position.
virtual bool updateProperties()
Updates the state and definition of properties based on the current connection status....
bool SetFocuserSpeed(int value)
SetFocuserSpeed Set Focuser speed.
bool setParkPos(uint32_t value)
ISwitch EraseEEPROMS[1]
Definition teenastro.h:199
bool setManualDec(uint32_t value)
INumberVectorProperty CurSpeedNP
Definition teenastro.h:140
virtual IPState MoveAbsFocuser(uint32_t ticks)
MoveFocuser the focuser to an absolute position.
INDI::PropertyNumber CfgMotorStepsPerRevolutionNP
Definition teenastro.h:192
virtual bool initProperties()
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
INDI::PropertyNumber CfgParkPosNP
Definition teenastro.h:129
virtual bool Handshake()
Performs a device-specific handshake after a connection is established. This method should be overrid...
Definition teenastro.cpp:82
bool ISNewNumberHelper(INDI::PropertyNumber &NP, double values[], char *names[], int n, bool res)
bool updateMotionConfig()
bool goTo(uint32_t position)
bool setGoToAcc(uint32_t value)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * FOCUS_TAB
FOCUS_TAB Where all the properties for focuser are located.
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_ATMOST1
Definition indiapi.h:172
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition indicom.c:548
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:759
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
@ TTY_TIME_OUT
Definition indicom.h:58
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 IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:509
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition indidevapi.c:44
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 IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition indidevapi.c:416
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
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#define MAXRBUF
Definition indidriver.c:52
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
Definition indilogger.h:56
#define DEBUGF(priority, msg,...)
Definition indilogger.h:57
#define getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2
char name[MAXINDINAME]
Definition indiapi.h:321
char name[MAXINDINAME]
Definition indiapi.h:369
char name[MAXINDINAME]
Definition indiapi.h:248
#define TAF_acc_min
Definition teenastro.cpp:48
#define TAF_res_max
Definition teenastro.cpp:52
#define TAF_steprot_default
Definition teenastro.cpp:38
#define TAF_speed_min
Definition teenastro.cpp:45
#define TAF_steprot_max
Definition teenastro.cpp:40
#define TAF_speed_max
Definition teenastro.cpp:46
#define TAF_speed_default
Definition teenastro.cpp:44
#define TAF_FOCUSER_TIMEOUT
Definition teenastro.cpp:58
#define TAF_res_min
Definition teenastro.cpp:51
std::unique_ptr< TeenAstroFocuser > teenAstroFocuser(new TeenAstroFocuser())
#define TAF_curr_min
Definition teenastro.cpp:33
#define TAF_acc_max
Definition teenastro.cpp:49
#define TAF_acc_default
Definition teenastro.cpp:47
#define TAF_curr_max
Definition teenastro.cpp:34
#define TAF_steprot_min
Definition teenastro.cpp:39
#define TAF_res_default
Definition teenastro.cpp:50
#define TAF_UI_STEPS
Definition teenastro.cpp:54
#define TAF_FOCUSER_BUFSIZE
Definition teenastro.cpp:59
#define TAF_curr_default
Definition teenastro.cpp:32
#define TAF_STEP(min, max)
Definition teenastro.cpp:55