Instrument Neutral Distributed Interface INDI 2.2.5
toup_sh20.cpp
Go to the documentation of this file.
1#include "toup_sh20.h"
3#include "lx200driver.h"
4#include "indicom.h"
5
6#include <libnova/transform.h>
7#include <cmath>
8#include <cstring>
9#include <stdio.h>
10#include <termios.h>
11#include <unistd.h>
12
32
34{
36
39
40 // Mount Type
41 MountTypeSP[TYPE_AZIMUTH].fill("Azimuth", "Azimuth", ISS_OFF);
42 MountTypeSP[TYPE_EQUATORIAL].fill("Equatorial", "Equatorial", ISS_ON);
43 MountTypeSP.fill(getDeviceName(), "MOUNT_TYPE", "Mount Type", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
44 MountTypeSP.load();
45 if (MountTypeSP[TYPE_EQUATORIAL].getState() == ISS_ON)
47
48 // Slew Rates
49 SlewRateSP[0].setLabel("0.25x");
50 SlewRateSP[1].setLabel("0.5x");
51 SlewRateSP[2].setLabel("1x");
52 SlewRateSP[3].setLabel("2x");
53 SlewRateSP[4].setLabel("4x");
54 SlewRateSP[5].setLabel("8x");
55 SlewRateSP[6].setLabel("20x");
56 SlewRateSP[7].setLabel("60x");
57 SlewRateSP[8].setLabel("720x");
58 SlewRateSP[9].setLabel("1440x");
61
62 // Guide Rate
63 GuideRateNP[0].fill("RATE", "Rate", "%.2f", 0.1, 0.9, 0.1, 0.5);
64 GuideRateNP.fill(getDeviceName(), "GUIDE_RATE", "Guiding Rate", MOTION_TAB, IP_RW, 60, IPS_IDLE);
65 GuideRateNP.load();
66
67 // Buzzer
68 BuzzerSP[BUZZER_OFF].fill("OFF", "Off", ISS_OFF);
69 BuzzerSP[BUZZER_LOW].fill("LOW", "Low", ISS_OFF);
70 BuzzerSP[BUZZER_HIGH].fill("HIGH", "High", ISS_ON);
71 BuzzerSP.fill(getDeviceName(), "BUZZER", "Buzzer", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
72 BuzzerSP.onUpdate([this]
73 {
74 if (setBuzzer(BuzzerSP.findOnSwitchIndex()))
75 {
76 BuzzerSP.setState(IPState::IPS_OK);
77 }
78 else
79 {
80 BuzzerSP.setState(IPState::IPS_ALERT);
81 }
82 BuzzerSP.apply();
83 });
84
85 // Meridian Flip Enable
86 MeridianFlipSP[INDI_ENABLED].fill("INDI_ENABLED", "Enabled", ISS_ON);
87 MeridianFlipSP[INDI_DISABLED].fill("INDI_DISABLED", "Disabled", ISS_OFF);
88 MeridianFlipSP.fill(getDeviceName(), "MERIDIAN_FLIP", "Meridian Flip", "Meridian Flip", IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
89 MeridianFlipSP.load();
90
91 // Meridian Flip Track
92 MeridianTrackSP[MERIDIAN_TRACK].fill("TRACK", "Track", ISS_ON);
93 MeridianTrackSP[MERIDIAN_STOP].fill("STOP", "Stop", ISS_OFF);
94 MeridianTrackSP.fill(getDeviceName(), "MERIDIAN_TRACK", "After Meridian", "Meridian Flip", IP_RW, ISR_1OFMANY,
95 60, IPS_IDLE);
96 MeridianTrackSP.load();
97
98 // Meridian Flip Limit
99 MeridianLimitNP[0].fill("LIMIT", "LIMIT (deg)", "%.f", -15, 15, 1, 0);
100 MeridianLimitNP.fill(getDeviceName(), "MERIDIAN_LIMIT", "Meridian Limit", "Meridian Flip", IP_RW, 60, IPS_IDLE);
101 MeridianLimitNP.load();
102
103 return true;
104}
105
107{
109
110 if (isConnected())
111 {
112 deleteProperty("TELESCOPE_MOUNT_TYPE");
113
114 getStartupData();
115
116 defineProperty(MountTypeSP);
117 defineProperty(GuideRateNP);
118 defineProperty(BuzzerSP);
119 if (MountTypeSP[TYPE_EQUATORIAL].getState() == ISS_ON)
120 {
121 defineProperty(MeridianFlipSP);
122 defineProperty(MeridianTrackSP);
123 defineProperty(MeridianLimitNP);
124 }
125 }
126 else
127 {
128 deleteProperty(MountTypeSP);
129 deleteProperty(GuideRateNP);
130 deleteProperty(BuzzerSP);
131 if (MountTypeSP[TYPE_EQUATORIAL].getState() == ISS_ON)
132 {
133 deleteProperty(MeridianFlipSP);
134 deleteProperty(MeridianTrackSP);
135 deleteProperty(MeridianLimitNP);
136 }
137 }
138
139 return true;
140}
141
142bool ToupSH20::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
143{
144 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
145 {
146 // Mount Type
147 if (MountTypeSP.isNameMatch(name))
148 {
149 int previousType = MountTypeSP.findOnSwitchIndex();
150 MountTypeSP.update(states, names, n);
151 IPState state = IPS_OK;
152 // Only update if already connected.
153 if (isConnected())
154 {
155 auto targetType = MountTypeSP.findOnSwitchIndex();
156 state = setMountType(targetType) ? IPS_OK : IPS_ALERT;
157 if (state == IPS_OK && previousType != targetType)
158 LOG_WARN("You must reconnect mount for change to take effect.");
159 }
160 MountTypeSP.setState(state);
161 MountTypeSP.apply();
162 saveConfig(MountTypeSP);
163 return true;
164 }
165
166 // Meridian Flip Enable
167 if (MeridianFlipSP.isNameMatch(name))
168 {
169 MeridianFlipSP.update(states, names, n);
170 auto rc = setMeridianFlipSettings(MeridianFlipSP[INDI_ENABLED].getState() == ISS_ON,
171 MeridianTrackSP[MERIDIAN_TRACK].getState() == ISS_ON,
172 MeridianLimitNP[0].getValue());
173 MeridianFlipSP.setState(rc ? IPS_OK : IPS_ALERT);
174 MeridianFlipSP.apply();
175 saveConfig(MeridianFlipSP);
176 return true;
177 }
178
179 // Meridian Flip Track
180 if (MeridianTrackSP.isNameMatch(name))
181 {
182 MeridianTrackSP.update(states, names, n);
183 auto rc = setMeridianFlipSettings(MeridianFlipSP[INDI_ENABLED].getState() == ISS_ON,
184 MeridianTrackSP[MERIDIAN_TRACK].getState() == ISS_ON,
185 MeridianLimitNP[0].getValue());
186 MeridianTrackSP.setState(rc ? IPS_OK : IPS_ALERT);
187 MeridianTrackSP.apply();
188 saveConfig(MeridianTrackSP);
189 return true;
190 }
191 }
192
193 return LX200Generic::ISNewSwitch(dev, name, states, names, n);
194}
195
196bool ToupSH20::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
197{
198 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
199 {
200 // Guide Rate
201 if (GuideRateNP.isNameMatch(name))
202 {
203 GuideRateNP.update(values, names, n);
204 GuideRateNP.setState(setGuideRate(GuideRateNP[0].getValue()) ? IPS_OK : IPS_ALERT);
205 GuideRateNP.apply();
206 return true;
207 }
208
209 // Meridian FLip Limit
210 if (MeridianLimitNP.isNameMatch(name))
211 {
212 MeridianLimitNP.update(values, names, n);
213 auto rc = setMeridianFlipSettings(MeridianFlipSP[INDI_ENABLED].getState() == ISS_ON,
214 MeridianTrackSP[MERIDIAN_TRACK].getState() == ISS_ON,
215 MeridianLimitNP[0].getValue());
216 MeridianLimitNP.setState(rc ? IPS_OK : IPS_ALERT);
217 MeridianLimitNP.apply();
218 saveConfig(MeridianLimitNP);
219 return true;
220 }
221 }
222
223 return LX200Generic::ISNewNumber(dev, name, values, names, n);
224}
225
227{
228 return "TOUPTEK SH20";
229}
230
232{
233 LOG_DEBUG("Checking SH20 connection...");
234
235 double targetRA = 0;
236 for (int i = 0; i < 2; i++)
237 {
238 if (getLX200RA(PortFD, &targetRA) == 0)
239 return true;
240
241 const struct timespec timeout = {0, 250000000L};
242 nanosleep(&timeout, NULL);
243 }
244
245 return false;
246}
247
248
250{
251 if (!isConnected())
252 return false;
253
254 bool isNotMove = true, isAtHome = false;
255
256 char status[DRIVER_LEN] = {0};
257 if (sendCommand(":GU#", status))
258 {
259 isNotMove = strchr(status, 'N');
260 isAtHome = strchr(status, 'H');
261 }
262
263 if (HomeSP.getState() == IPS_BUSY && isAtHome)
264 {
265 HomeSP.reset();
267 LOG_INFO("At home position now.");
268 HomeSP.apply();
270 }
271 else if (TrackState == SCOPE_SLEWING)
272 {
273 // Check if LX200 is done slewing
274 if (isNotMove)
275 {
277 LOG_INFO("Slew is complete. Tracking...");
278 }
279 }
280 else if (TrackState == SCOPE_PARKING)
281 {
282 if (isNotMove)
283 {
284 SetParked(true);
285 }
286 }
287 else
288 {
289 char response[DRIVER_LEN] = {0};
290 if (sendCommand(":GTS#", response))
291 {
292 auto wasTracking = TrackStateSP[INDI_ENABLED].getState() == ISS_ON;
293 auto nowTracking = response[0] == '1';
294 if (wasTracking != nowTracking)
295 TrackState = nowTracking ? SCOPE_TRACKING : SCOPE_IDLE;
296 }
297 }
298
300 {
302 LOG_ERROR("Error reading RA/DEC.");
303 EqNP.apply();
304 return false;
305 }
306
307 if (HasPierSide())
308 {
309 char response[DRIVER_LEN] = {0};
310 if (sendCommand(":Gm#", response))
311 {
312 if (response[0] == '1')
314 else if (response[0] == '0')
316 else
318 }
319 }
320
322
323 return true;
324}
325
329bool ToupSH20::updateLocation(double latitude, double longitude, double elevation)
330{
331 INDI_UNUSED(elevation);
332 int d = 0, m = 0, s = 0;
333
334 // JM: INDI Longitude is 0 to 360 increasing EAST. Standard East is Positive, West is negative
335 if (longitude > 180)
336 longitude = longitude - 360;
337
338 char command[DRIVER_LEN] = {0};
339 getSexComponents(longitude, &d, &m, &s);
340 snprintf(command, DRIVER_LEN, ":Sg%c%03d*%02d:%02d#", longitude >= 0 ? '+' : '-', std::abs(d), m, s);
341 if (setStandardProcedure(PortFD, command) < 0)
342 {
343 LOG_ERROR("Error setting site longitude coordinates");
344 return false;
345 }
346
347 getSexComponents(latitude, &d, &m, &s);
348 snprintf(command, DRIVER_LEN, ":St%c%02d*%02d:%02d#", latitude >= 0 ? '+' : '-', std::abs(d), m, s);
349 if (setStandardProcedure(PortFD, command) < 0)
350 {
351 LOG_ERROR("Error setting site latitude coordinates");
352 return false;
353 }
354
355 return true;
356}
357
361bool ToupSH20::setUTCOffset(double offset)
362{
363 int h = 0, m = 0, s = 0;
364 char command[DRIVER_LEN] = {0};
365 getSexComponents(offset, &h, &m, &s);
366
367 snprintf(command, DRIVER_LEN, ":SG%c%02d:%02d#", offset >= 0 ? '+' : '-', std::abs(h), m);
368 return setStandardProcedure(PortFD, command) == 0;
369}
370
371bool ToupSH20::setLocalDate(uint8_t days, uint8_t months, uint16_t years)
372{
373 char command[DRIVER_LEN] = {0};
374 snprintf(command, DRIVER_LEN, ":SC%02d/%02d/%02d#", months, days, years % 100);
375 return setStandardProcedure(PortFD, command) == 0;
376}
377
381bool ToupSH20::Goto(double ra, double dec)
382{
383 const struct timespec timeout = {0, 100000000L};
384
385 targetRA = ra;
386 targetDEC = dec;
387 char RAStr[64] = {0}, DecStr[64] = {0};
388 int fracbase = 0;
389
390 switch (getLX200EquatorialFormat())
391 {
393 fracbase = 360000;
394 break;
397 default:
398 fracbase = 3600;
399 break;
400 }
401
402 fs_sexa(RAStr, targetRA, 2, fracbase);
403 fs_sexa(DecStr, targetDEC, 2, fracbase);
404
405 // If moving, let's stop it first.
406 if (EqNP.getState() == IPS_BUSY)
407 {
408 if (!isSimulation() && abortSlew(PortFD) < 0)
409 {
411 LOG_ERROR("Abort slew failed.");
412 AbortSP.apply();
413 return false;
414 }
415
418 LOG_ERROR("Slew aborted.");
419 AbortSP.apply();
420 EqNP.apply();
421
423 {
431 }
432
433 // sleep for 100 mseconds
434 nanosleep(&timeout, nullptr);
435 }
436
437 if (!isSimulation())
438 {
440 {
442 LOG_ERROR("Error setting RA/DEC.");
443 EqNP.apply();
444 return false;
445 }
446
447 int err = Slew(PortFD);
448
449 // for sh20 0:failed, 1:success
450 if (err == 0)
451 {
452 LOGF_ERROR("Error Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
453 slewError(err);
454 return false;
455 }
456 }
457
459 //EqNP.s = IPS_BUSY;
460
461 LOGF_INFO("Slewing to RA: %s - DEC: %s", RAStr, DecStr);
462
463 return true;
464}
465
470{
471 char command[DRIVER_LEN] = {0};
472 snprintf(command, DRIVER_LEN, ":R%d#", index);
473 return sendCommand(command);
474}
475
480{
481 char response[DRIVER_LEN] = {0};
482 bool rc = sendCommand(enabled ? ":Te#" : ":Td#", response, 4, 1);
483 return rc && response[0] == '1';
484}
485
490{
491 char response[DRIVER_LEN] = {0};
492 bool rc = sendCommand(":SPc#", response, 5, 1);
493 return rc && response[0] == '1';
494}
495
497{
498 if (!sendCommand(":MP1#"))
499 return false;
501 return true;
502}
503
505{
506 if (!sendCommand(":MP0#"))
507 return false;
509 SetParked(false);
510 return true;
511}
512
517{
518 switch (action)
519 {
520 case HOME_GO:
521 if (goHome())
522 return IPS_BUSY;
523 else
524 return IPS_ALERT;
525
526 case HOME_FIND:
527 if (findHome())
528 return IPS_OK;
529 else
530 return IPS_ALERT;
531
532 default:
533 return IPS_ALERT;
534
535 }
536}
537
541bool ToupSH20::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
542{
543 int nbytes_written = 0, nbytes_read = 0, rc = -1;
544
545 tcflush(PortFD, TCIOFLUSH);
546
547 if (cmd_len > 0)
548 {
549 char hex_cmd[DRIVER_LEN * 3] = {0};
550 hexDump(hex_cmd, cmd, cmd_len);
551 LOGF_DEBUG("CMD <%s>", hex_cmd);
552 rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
553 }
554 else
555 {
556 LOGF_DEBUG("CMD <%s>", cmd);
557 rc = tty_write_string(PortFD, cmd, &nbytes_written);
558 }
559
560 if (rc != TTY_OK)
561 {
562 char errstr[MAXRBUF] = {0};
563 tty_error_msg(rc, errstr, MAXRBUF);
564 LOGF_ERROR("Serial write error: %s.", errstr);
565 return false;
566 }
567
568 if (res == nullptr)
569 {
570 tcdrain(PortFD);
571 return true;
572 }
573
574 if (res_len > 0)
575 rc = tty_read(PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
576 else
577 rc = tty_nread_section(PortFD, res, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
578
579 if (rc != TTY_OK)
580 {
581 char errstr[MAXRBUF] = {0};
582 tty_error_msg(rc, errstr, MAXRBUF);
583 LOGF_ERROR("Serial read error: %s.", errstr);
584 return false;
585 }
586
587 if (res_len > 0)
588 {
589 char hex_res[DRIVER_LEN * 3] = {0};
590 hexDump(hex_res, res, res_len);
591 LOGF_DEBUG("RES <%s>", hex_res);
592 }
593 else
594 {
595 LOGF_DEBUG("RES <%s>", res);
596 }
597
598 tcflush(PortFD, TCIOFLUSH);
599
600 return true;
601}
602
603void ToupSH20::hexDump(char * buf, const char * data, int size)
604{
605 for (int i = 0; i < size; i++)
606 sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
607
608 if (size > 0)
609 buf[3 * size - 1] = '\0';
610}
611
615void ToupSH20::getStartupData()
616{
617 InitPark();
618 getMountType();
619 getTrackMode();
620 getGuideRate();
621 getBuzzer();
622 if (MountTypeSP[TYPE_EQUATORIAL].getState() == ISS_ON)
623 getMeridianFlipSettings();
624}
625
629bool ToupSH20::setMountType(int type)
630{
631 return sendCommand((type == TYPE_EQUATORIAL) ? ":AP#" : ":AA#");
632}
633
634bool ToupSH20::getMountType()
635{
636 char response[DRIVER_LEN] = {0};
637 if (sendCommand(":GU#", response))
638 {
639 MountTypeSP.reset();
640 MountTypeSP[TYPE_AZIMUTH].setState(strchr(response, 'Z') ? ISS_ON : ISS_OFF);
641 MountTypeSP[TYPE_EQUATORIAL].setState(strchr(response, 'G') ? ISS_ON : ISS_OFF);
642 MountTypeSP.setState(IPS_OK);
643 return true;
644 }
645 else
646 {
647 MountTypeSP.setState(IPS_ALERT);
648 return false;
649 }
650}
651
655bool ToupSH20::goHome()
656{
657 return sendCommand(":MH#");
658}
659
660bool ToupSH20::findHome()
661{
662 const char cmd[] = ":MFH#";
663 char status = '0';
664 return sendCommand(cmd, &status, strlen(cmd), sizeof(status)) && status == '1';
665}
666
670bool ToupSH20::getTrackMode()
671{
672 char response[DRIVER_LEN] = {0};
673 if (sendCommand(":GT#", response))
674 {
676 auto onIndex = response[0];
677 TrackModeSP[onIndex].setState(ISS_ON);
678 return true;
679 }
680
682 return false;
683
684}
685
689bool ToupSH20::setGuideRate(double value)
690{
691 char command[DRIVER_LEN] = {0};
692 snprintf(command, DRIVER_LEN, ":Sgr%.2f#", value);
693 return sendCommand(command);
694}
695
696bool ToupSH20::getGuideRate()
697{
698 char response[DRIVER_LEN] = {0};
699 if (sendCommand(":Ggr#", response))
700 {
701 double value = 0;
702 if (sscanf(response, "%lf", &value) == 1)
703 {
704 GuideRateNP[0].setValue(value);
705 return true;
706 }
707 }
708 GuideRateNP.setState(IPS_ALERT);
709 return false;
710}
711
715bool ToupSH20::setBuzzer(int value)
716{
717 char command[DRIVER_LEN] = {0};
718 snprintf(command, DRIVER_LEN, ":SBz%d#", value);
719 return sendCommand(command);
720}
721
722bool ToupSH20::getBuzzer()
723{
724 char response[DRIVER_LEN] = {0};
725 if (sendCommand(":GBz#", response))
726 {
727 BuzzerSP.reset();
728 auto onIndex = response[0];
729 BuzzerSP[onIndex].setState(ISS_ON);
730 BuzzerSP.setState(IPS_OK);
731 return true;
732 }
733 else
734 {
735 BuzzerSP.setState(IPS_ALERT);
736 return false;
737 }
738}
739
743bool ToupSH20::setMeridianFlipSettings(bool enabled, bool track, double limit)
744{
745 char command[DRIVER_LEN] = {0};
746 snprintf(command, DRIVER_LEN, ":STa%d%d%c%02d#", enabled ? 1 : 0, track ? 1 : 0,
747 limit >= 0 ? '+' : '-', static_cast<int>(std::abs(limit)));
748 char response[2] = {0};
749 auto rc = sendCommand(command, response, -1, 1);
750 return rc && response[0] == '1';
751}
752
753bool ToupSH20::getMeridianFlipSettings()
754{
755 char response[DRIVER_LEN] = {0};
756 if (sendCommand(":GTa#", response))
757 {
758 if (strlen(response) >= 5)
759 {
760 MeridianFlipSP.reset();
761 MeridianFlipSP[response[0] == '1' ? INDI_ENABLED : INDI_DISABLED].setState(ISS_ON);
762 MeridianFlipSP.setState(IPS_OK);
763
764 MeridianTrackSP.reset();
765 MeridianTrackSP[response[1] == '1' ? MERIDIAN_TRACK : MERIDIAN_STOP].setState(ISS_ON);
766 MeridianTrackSP.setState(IPS_OK);
767
768 char *sign = &response[2];
769 char *limit = &response[3];
770 int limitValue = atoi(limit);
771 if (*sign == '-')
772 limitValue = -limitValue;
773 MeridianLimitNP[0].setValue(limitValue);
774 MeridianLimitNP.setState(IPS_OK);
775
776 return true;
777 }
778 }
779
780 MeridianFlipSP.setState(IPS_ALERT);
781 MeridianTrackSP.setState(IPS_ALERT);
782 MeridianLimitNP.setState(IPS_ALERT);
783 return false;
784}
bool isConnected() const
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
bool isSimulation() const
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool load()
load Attempt to load property values from configuration file.
void setLabel(const char *label)
bool isNameMatch(const char *otherName) const
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)
void onUpdate(const std::function< void()> &callback)
TelescopeStatus TrackState
void SetTelescopeCapability(uint32_t cap, uint8_t slewRateCount)
SetTelescopeCapability sets the Telescope capabilities. All capabilities must be initialized.
virtual void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
uint32_t GetTelescopeCapability() const
GetTelescopeCapability returns the capability of the Telescope.
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
void setPierSide(TelescopePierSide side)
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
void SetParkDataType(TelescopeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual void slewError(int slewCode)
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
void setLX200Capability(uint32_t cap)
virtual bool ReadScopeStatus() override
Read telescope status.
virtual const char * getDefaultName() override
virtual bool Park() override
Park the telescope to its home position.
virtual bool checkConnection() override
virtual bool SetSlewRate(int index) override
Override - Slew rate.
virtual bool Goto(double ra, double dec) override
Override - Goto.
virtual bool SetCurrentPark() override
Override - Park.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Override - Location.
virtual bool setUTCOffset(double offset) override
Override - Date.
virtual bool setLocalDate(uint8_t days, uint8_t months, uint16_t years) override
virtual bool SetTrackEnabled(bool enabled) override
Override - Track enable.
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual IPState ExecuteHomeAction(TelescopeHomeAction action) override
Override - Home.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
Definition toup_sh20.cpp:33
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
INDI::PropertySwitch AbortSP
INDI::PropertySwitch MovementNSSP
INDI::PropertyNumber EqNP
INDI::PropertySwitch TrackStateSP
INDI::PropertySwitch HomeSP
INDI::PropertySwitch SlewRateSP
INDI::PropertySwitch TrackModeSP
INDI::PropertySwitch MovementWESP
double ra
double dec
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
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
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
void getSexComponents(double value, int *d, int *m, int *s)
Definition indicom.c:243
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition indicom.c:548
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string. sprint the variable a in sexagesimal format into out[].
Definition indicom.c:130
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
#define INDI_UNUSED(x)
Definition indidevapi.h:132
#define MAXRBUF
Definition indidriver.c:52
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_DEBUG(txt)
Definition indilogger.h:75
#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 getDeviceName
int setObjectRA(int fd, double ra, bool addSpace)
int getLX200EquatorialFormat()
int setStandardProcedure(int fd, const char *data)
int setObjectDEC(int fd, double dec, bool addSpace)
int abortSlew(int fd)
int Slew(int fd)
#define getLX200DEC(fd, x)
@ LX200_24
Definition lx200driver.h:64
#define getLX200RA(fd, x)
@ LX200_EQ_LONGER_FORMAT
Definition lx200driver.h:52
@ LX200_EQ_SHORT_FORMAT
Definition lx200driver.h:50
@ LX200_EQ_LONG_FORMAT
Definition lx200driver.h:51
uint16_t type
Definition pwc-ioctl.h:0
uint8_t cmd[4]
Definition pwc-ioctl.h:2