Instrument Neutral Distributed Interface INDI 2.2.5
pyxis.cpp
Go to the documentation of this file.
1/*
2 Optec Pyrix Rotator
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
21#include "pyxis.h"
22
23#include "indicom.h"
25
26#include <cmath>
27#include <cstring>
28#include <memory>
29#include <termios.h>
30
31#define PYXIS_TIMEOUT 3
32#define PYRIX_BUF 7
33#define PYRIX_CMD 6
34#define SETTINGS_TAB "Settings"
35
36// Recommended default rates for 3 inch and 2 inch rotators
37#define PYXIS_3INCH_RATE 6
38#define PYXIS_2INCH_RATE 8
39
40// Number of steps per degree for rotators
41#define PYXIS_3INCH_PER_DEG (128)
42#define PYXIS_2INCH_PER_DEG 14
43
44// 100ms poll rate while rotating
45#define POLL_100MS 100
46
47std::unique_ptr<Pyxis> pyxis(new Pyxis());
48
56
58{
60
61 // Rotation Rate
62 RotationRateNP[0].fill("RATE", "Rate", "%.f", 0, 99, 10, 8);
63 RotationRateNP.fill(getDeviceName(), "ROTATION_RATE", "Rotation", SETTINGS_TAB, IP_RW, 0,
64 IPS_IDLE);
65
66 // Stepping
67 SteppingSP[FULL_STEP].fill("FULL_STEP", "Full", ISS_OFF);
68 SteppingSP[HALF_STEP].fill("HALF_STEP", "Half", ISS_OFF);
69 SteppingSP.fill( getDeviceName(), "STEPPING_RATE", "Stepping", SETTINGS_TAB, IP_RW,
71
72 // Power
73 PowerSP[POWER_SLEEP].fill("POWER_SLEEP", "Sleep", ISS_OFF);
74 PowerSP[POWER_WAKEUP].fill("POWER_WAKEUP", "Wake Up", ISS_OFF);
75 PowerSP.fill(getDeviceName(), "POWER_STATE", "Power", SETTINGS_TAB, IP_RW, ISR_ATMOST1, 0,
76 IPS_IDLE);
77
78 // Firmware version
79 FirmwareTP[0].fill("FIRMWARE_VERSION", "Version", "Unknown");
80 FirmwareTP.fill(getDeviceName(), "FIRMWARE_VERSION", "Firmware", INFO_TAB, IP_RO, 0, IPS_IDLE);
81
82 // Firmware version
83 ModelTP[0].fill("HARDWARE_MODEL", "Model", "Unknown");
84 ModelTP.fill(getDeviceName(), "HARDWARE_MODEL", "Model", INFO_TAB, IP_RO, 0, IPS_IDLE);
85
86
88
89 return true ;
90}
91
93{
94 if (Ack())
95 return true;
96
97 LOG_INFO("Error retrieving data from Pyxis, please ensure Pyxis controller is powered and the port is correct.");
98 return false;
99}
100
102{
103 return "Pyxis";
104}
105
107{
109
110 if (isConnected())
111 {
112 defineProperty(RotationRateNP) ;
113 defineProperty(SteppingSP);
114 defineProperty(PowerSP);
115 defineProperty(FirmwareTP) ;
116 defineProperty(ModelTP) ;
117
118 queryParams();
119 }
120 else
121 {
122 deleteProperty(RotationRateNP);
123 deleteProperty(SteppingSP);
124 deleteProperty(PowerSP);
125 deleteProperty(FirmwareTP) ;
126 deleteProperty(ModelTP) ;
127 }
128
129 return true;
130}
131
132void Pyxis::queryParams()
133{
135 // Reverse Parameter
137 int dir = getReverseStatus();
138
141 if (dir == 0)
143 else if (dir == 1)
145 else
147
149
150 // Firmware version parameter
151 std::string sversion = getVersion() ;
152 FirmwareTP[0].setText(sversion.c_str()) ;
153 FirmwareTP.setState(IPS_OK);
154 FirmwareTP.apply() ;
155
156 LOGF_DEBUG("queryParms firmware = %s", sversion.c_str()) ;
157
158 // Firmware tells us device type, 3 inch or 2 inch, which defines the correct default rotation rate
159 if (atof(sversion.c_str()) >= 3)
160 {
161 uint16_t rate = (atof(sversion.c_str()) >= 3 ? PYXIS_3INCH_RATE : PYXIS_2INCH_RATE) ;
162 bool rc = setRotationRate(rate) ;
163 LOGF_DEBUG("queryParms rate = %d, firmware = %s", rate, sversion.c_str()) ;
164 if (rc)
165 {
166 RotationRateNP.setState(IPS_OK) ;
167 RotationRateNP[0].setValue(rate) ;
168 RotationRateNP.apply() ;
169
170 ModelTP[0].setText("Pyxis 3 Inch");
171 ModelTP.setState(IPS_OK);
172 ModelTP.apply();
173 }
174 }
175 else
176 {
177 ModelTP[0].setText("Pyxis 2 Inch") ;
178 ModelTP.setState(IPS_OK);
179 ModelTP.apply() ;
180 }
181
182}
183
184bool Pyxis::Ack()
185{
186 const char *cmd = "CCLINK";
187 char res[1] = {0};
188
189 int nbytes_written = 0, nbytes_read = 0, rc = -1;
190 char errstr[MAXRBUF];
191
192 LOGF_DEBUG("CMD <%s>", cmd);
193
194 tcflush(PortFD, TCIOFLUSH);
195
196 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
197 {
198 tty_error_msg(rc, errstr, MAXRBUF);
199 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
200 return false;
201 }
202
203 if ( (rc = tty_read(PortFD, res, 1, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
204 {
205 tty_error_msg(rc, errstr, MAXRBUF);
206 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
207 return false;
208 }
209
210 LOGF_DEBUG("RES <%c>", res[0]);
211
212 tcflush(PortFD, TCIOFLUSH);
213
214 if (res[0] != '!')
215 {
216 LOG_ERROR("Cannot establish communication. Check power is on and homing is complete.");
217 return false;
218 }
219
220 return true;
221}
222
223bool Pyxis::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
224{
225 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
226 {
227 if (RotationRateNP.isNameMatch(name))
228 {
229 bool rc = setRotationRate(static_cast<uint8_t>(values[0]));
230 if (rc)
231 {
232 RotationRateNP.setState(IPS_OK);
233 RotationRateNP[0].setValue(values[0]);
234 }
235 else
236 RotationRateNP.setState(IPS_ALERT);
237
238 RotationRateNP.apply();
239 return true;
240 }
241 }
242
243 return Rotator::ISNewNumber(dev, name, values, names, n);
244}
245
246bool Pyxis::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
247{
248 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
249 {
251 // Stepping
253 if (SteppingSP.isNameMatch(name))
254 {
255 bool rc = false;
256 if (!strcmp(IUFindOnSwitchName(states, names, n), SteppingSP[FULL_STEP].getName()))
257 rc = setSteppingMode(FULL_STEP);
258 else
259 rc = setSteppingMode(HALF_STEP);
260
261
262 if (rc)
263 {
264 SteppingSP.update(states, names, n);
265 SteppingSP.setState(IPS_OK);
266 }
267 else
268 SteppingSP.setState(IPS_ALERT);
269
270 SteppingSP.apply();
271 return true;
272 }
273
275 // Power
277 if (PowerSP.isNameMatch(name))
278 {
279 bool rc = false;
280 if (!strcmp(IUFindOnSwitchName(states, names, n), PowerSP[POWER_WAKEUP].getName()))
281 {
282 // If not sleeping
283 if (PowerSP[POWER_SLEEP].getState() == ISS_OFF)
284 {
285 PowerSP.setState(IPS_OK);
286 LOG_WARN("Controller is not in sleep mode.");
287 PowerSP.apply();
288 return true;
289 }
290
291 rc = wakeupController();
292
293 if (rc)
294 {
295 PowerSP.reset();
296 PowerSP.setState(IPS_OK);
297 LOG_INFO("Controller is awake.");
298 }
299 else
300 PowerSP.setState(IPS_ALERT);
301
302 PowerSP.apply();
303 return true;
304 }
305 else
306 {
307 bool rc = sleepController();
308 PowerSP.reset();
309 if (rc)
310 {
311 PowerSP.setState(IPS_OK);
312 PowerSP[POWER_SLEEP].setState(ISS_ON);
313 LOG_INFO("Controller in sleep mode. No functions can be used until controller is waken up.");
314 }
315 else
316 PowerSP.setState(IPS_ALERT);
317
318 PowerSP.apply();
319 return true;
320 }
321 }
322 }
323
324 return Rotator::ISNewSwitch(dev, name, states, names, n);
325}
326
327bool Pyxis::setSteppingMode(uint8_t mode)
328{
329 char cmd[PYRIX_BUF] = {0};
330
331 int nbytes_written = 0, rc = -1;
332 char errstr[MAXRBUF];
333
334 snprintf(cmd, PYRIX_BUF, "CZ%dxxx", mode);
335
336 LOGF_DEBUG("CMD <%s>", cmd);
337
338 tcflush(PortFD, TCIOFLUSH);
339
340 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
341 {
342 tty_error_msg(rc, errstr, MAXRBUF);
343 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
344 return false;
345 }
346
347 return true;
348}
349
350bool Pyxis::setRotationRate(uint8_t rate)
351{
352 char cmd[PYRIX_BUF] = {0};
353 int nbytes_written = 0, rc = -1;
354 char errstr[MAXRBUF];
355
356 char res[1] = { 0 } ;
357 int nbytes_read = 0 ;
358
359 snprintf(cmd, PYRIX_BUF, "CTxx%02d", rate);
360
361 LOGF_DEBUG("CMD <%s>", cmd);
362
363 tcflush(PortFD, TCIOFLUSH);
364
365 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
366 {
367 tty_error_msg(rc, errstr, MAXRBUF);
368 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
369 return false;
370 }
371
372 if ( (rc = tty_read(PortFD, res, 1, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
373 {
374 tty_error_msg(rc, errstr, MAXRBUF);
375 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
376 return false;
377 }
378
379 tcflush(PortFD, TCIOFLUSH);
380
381 LOGF_DEBUG("RES <%c>", res[0]);
382
383 return (res[0] == '!');
384}
385
386bool Pyxis::sleepController()
387{
388 const char *cmd = "CSLEEP";
389
390 int nbytes_written = 0, rc = -1;
391 char errstr[MAXRBUF];
392
393 LOGF_DEBUG("CMD <%s>", cmd);
394
395 tcflush(PortFD, TCIOFLUSH);
396
397 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
398 {
399 tty_error_msg(rc, errstr, MAXRBUF);
400 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
401 return false;
402 }
403
404 return true;
405}
406
407bool Pyxis::wakeupController()
408{
409 const char *cmd = "CWAKEUP";
410 char res[1] = { 0 };
411
412 int nbytes_written = 0, nbytes_read = 0, rc = -1;
413 char errstr[MAXRBUF];
414
415 LOGF_DEBUG("CMD <%s>", cmd);
416
417 tcflush(PortFD, TCIOFLUSH);
418
419 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
420 {
421 tty_error_msg(rc, errstr, MAXRBUF);
422 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
423 return false;
424 }
425
426 if ( (rc = tty_read(PortFD, res, 1, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
427 {
428 tty_error_msg(rc, errstr, MAXRBUF);
429 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
430 return false;
431 }
432
433 tcflush(PortFD, TCIOFLUSH);
434
435 LOGF_DEBUG("RES <%c>", res[0]);
436
437 return (res[0] == '!');
438}
439
441{
442 const char *cmd = "CHOMES";
443
444 int nbytes_written = 0, rc = -1;
445 char errstr[MAXRBUF];
446
447 LOGF_DEBUG("CMD <%s>", cmd);
448
449 tcflush(PortFD, TCIOFLUSH);
450
451 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
452 {
453 tty_error_msg(rc, errstr, MAXRBUF);
454 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
455 return IPS_ALERT;
456 }
457
458 return IPS_BUSY;
459}
460
462{
463 char cmd[PYRIX_BUF] = {0};
464
465 int nbytes_written = 0, rc = -1;
466 char errstr[MAXRBUF];
467
468 uint16_t current = static_cast<uint16_t>(GotoRotatorNP[0].getValue()) ;
469
470 targetPA = static_cast<uint16_t>(round(angle));
471
472 if (targetPA > 359)
473 targetPA = 0;
474
475 // Rotator will only rotation +-180 degrees from home (0 degrees) so it make take
476 // the long way to avoid cable wrap
477 if (current <= 180 && targetPA < 180)
478 direction = (targetPA >= current ? 1 : -1) ;
479 else if (current <= 180 && targetPA > 180)
480 direction = -1 ;
481 else if (current > 180 && targetPA >= 180)
482 direction = (targetPA >= current ? 1 : -1) ;
483 else if (current > 180 && targetPA < 180)
484 direction = 1 ;
485
486 snprintf(cmd, PYRIX_BUF, "CPA%03d", targetPA);
487
488 LOGF_DEBUG("CMD <%s>", cmd);
489
490 tcflush(PortFD, TCIOFLUSH);
491
492 if ( (rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
493 {
494 tty_error_msg(rc, errstr, MAXRBUF);
495 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
496 return IPS_ALERT;
497 }
498
499 return IPS_BUSY;
500}
501
502bool Pyxis::ReverseRotator(bool enabled)
503{
504 char cmd[PYRIX_BUF] = {0};
505
506 int nbytes_written = 0, rc = -1;
507 char errstr[MAXRBUF];
508
509 snprintf(cmd, PYRIX_BUF, "CD%dxxx", enabled ? 1 : 0);
510
511 LOGF_DEBUG("CMD <%s>", cmd);
512
513 tcflush(PortFD, TCIOFLUSH);
514
515 if ( (rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
516 {
517 tty_error_msg(rc, errstr, MAXRBUF);
518 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
519 return false;
520 }
521
522 return true;
523}
524
526{
527 if (!isConnected() || PowerSP[POWER_SLEEP].getState() == ISS_ON)
528 {
530 return;
531 }
532
533 // Record last state
534 auto currentState = GotoRotatorNP.getState();
535
537 {
538 if (isMotionComplete())
539 {
540 currentState = IPS_OK;
544 LOG_INFO("Homing is complete.");
545 }
546 else
547 {
548 // Fast timer
550 return;
551 }
552 }
553 else if (GotoRotatorNP.getState() == IPS_BUSY)
554 {
555 if (!isMotionComplete())
556 {
557 LOG_DEBUG("Motion in progress.") ;
559 return;
560 }
561
562 currentState = IPS_OK;
563 LOG_INFO("Motion complete.") ;
564 }
565
566 // Update PA
567 uint16_t PA = GotoRotatorNP[0].getValue();
568 getPA(PA);
569
570 // If either PA or state changed, update the property.
571 if ( (PA != static_cast<uint16_t>(GotoRotatorNP[0].getValue())) || currentState != GotoRotatorNP.getState())
572 {
573 GotoRotatorNP[0].setValue(PA);
574 GotoRotatorNP.setState(currentState);
576 }
577
579}
580
581bool Pyxis::isMotionComplete()
582{
583 int nbytes_read = 0, rc = -1;
584 char errstr[MAXRBUF];
585 char res[PYXIS_3INCH_PER_DEG + 1] = { 0 };
586
587 bool pyxis3inch = atoi(FirmwareTP[0].getText()) >= 3 ;
588
589 if ( (rc = tty_nread_section(PortFD, res, (pyxis3inch ? PYXIS_3INCH_PER_DEG : PYXIS_2INCH_PER_DEG), 'F', 1,
590 &nbytes_read)) != TTY_OK)
591 {
592 // '!' motion is not complete yet
593 if (rc == TTY_TIME_OUT)
594 return false;
595 else if (rc == TTY_OVERFLOW)
596 {
597 LOGF_DEBUG("RES <%s>", res);
598
599 int current = static_cast<uint16_t>(GotoRotatorNP[0].getValue()) ;
600
601 current = current + direction ;
602 if (current < 0) current = 359 ;
603 if (current > 360) current = 1 ;
604
605 GotoRotatorNP[0].setValue(current );
607
608 LOGF_DEBUG("ANGLE = %d", current) ;
609 LOGF_DEBUG("TTY_OVERFLOW, nbytes_read = %d", nbytes_read) ;
610 return false ;
611 }
612
613 tty_error_msg(rc, errstr, MAXRBUF);
614 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
615
617 {
620 LOG_ERROR("Homing failed. Check possible jam.");
621 tcflush(PortFD, TCIOFLUSH);
622 }
623
624 return false;
625 }
626
627 LOGF_DEBUG("RES <%s>", res);
628 return true;
629}
630
631#if 0
632bool Pyxis::isMotionComplete()
633{
634 int nbytes_read = 0, rc = -1;
635 char errstr[MAXRBUF];
636 char res[1] = { 0 };
637
638 if ( (rc = tty_read(PortFD, res, 1, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
639 {
640 tty_error_msg(rc, errstr, MAXRBUF);
641 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
642 return false;
643 }
644
645 LOGF_DEBUG("RES <%c>", res[0]);
646
647 // Homing still in progress
648 if (res[0] == '!')
649 return false;
650 // Homing is complete
651 else if (res[0] == 'F')
652 return true;
653 // Error
654 else if (HomeRotatorSP.s == IPS_BUSY)
655 {
658 LOG_ERROR("Homing failed. Check possible jam.");
659 tcflush(PortFD, TCIOFLUSH);
660 }
661
662 return false;
663}
664#endif
665
666std::string Pyxis::getVersion()
667{
668 const char *cmd = "CVxxxx";
669 char res[4] = {0};
670
671 int nbytes_written = 0, nbytes_read = 0, rc = -1;
672 char errstr[MAXRBUF];
673
674 LOGF_DEBUG("CMD <%s>", cmd);
675
676 tcflush(PortFD, TCIOFLUSH);
677
678 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
679 {
680 tty_error_msg(rc, errstr, MAXRBUF);
681 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
682 return std::string("");;
683 }
684
685 if ( (rc = tty_read(PortFD, res, 3, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
686 {
687 tty_error_msg(rc, errstr, MAXRBUF);
688 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
689 return std::string("") ;
690 }
691
692 tcflush(PortFD, TCIOFLUSH);
693
694 LOGF_DEBUG("RES <%s>", res);
695
696 if (res[0] == '!')
697 return std::string("");
698
699 return std::string(res) ;;
700}
701
702
703bool Pyxis::getPA(uint16_t &PA)
704{
705 const char *cmd = "CGETPA";
706 char res[4] = {0};
707
708 int nbytes_written = 0, nbytes_read = 0, rc = -1;
709 char errstr[MAXRBUF];
710
711 LOGF_DEBUG("CMD <%s>", cmd);
712
713 tcflush(PortFD, TCIOFLUSH);
714
715 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
716 {
717 tty_error_msg(rc, errstr, MAXRBUF);
718 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
719 return false;
720 }
721
722 if ( (rc = tty_read(PortFD, res, 3, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
723 {
724 tty_error_msg(rc, errstr, MAXRBUF);
725 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
726 return false;
727 }
728
729 tcflush(PortFD, TCIOFLUSH);
730
731 LOGF_DEBUG("RES <%s>", res);
732
733 if (res[0] == '!')
734 return false;
735
736 PA = atoi(res);
737
738 return true;
739}
740
741int Pyxis::getReverseStatus()
742{
743 const char *cmd = "CMREAD";
744 char res[1] = {0};
745
746 int nbytes_written = 0, nbytes_read = 0, rc = -1;
747 char errstr[MAXRBUF];
748
749 LOGF_DEBUG("CMD <%s>", cmd);
750
751 tcflush(PortFD, TCIOFLUSH);
752
753 if ( (rc = tty_write(PortFD, cmd, PYRIX_CMD, &nbytes_written)) != TTY_OK)
754 {
755 tty_error_msg(rc, errstr, MAXRBUF);
756 LOGF_ERROR("%s: %s.", __FUNCTION__, errstr);
757 return -1;
758 }
759
760 if ( (rc = tty_read(PortFD, res, 1, PYXIS_TIMEOUT, &nbytes_read)) != TTY_OK)
761 {
762 tty_error_msg(rc, errstr, MAXRBUF);
763 LOGF_ERROR("%s error: %s.", __FUNCTION__, errstr);
764 return -1;
765 }
766
767 tcflush(PortFD, TCIOFLUSH);
768
769 LOGF_DEBUG("RES <%c>", res[0]);
770
771 return (res[0] == '1' ? 1 : 0);
772}
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
bool isConnected() const
INDI::PropertyText getText(const char *name) const
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)
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 setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool isNameMatch(const char *otherName) const
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 fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
INDI::PropertySwitch HomeRotatorSP
INDI::PropertySwitch ReverseRotatorSP
INDI::PropertyNumber GotoRotatorNP
Connection::Serial * serialConnection
Definition indirotator.h:95
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
void setRotatorConnection(const uint8_t &value)
setRotatorConnection Set Rotator connection mode. Child class should call this in the constructor bef...
Definition pyxis.h:27
virtual IPState HomeRotator() override
HomeRotator Go to home position.
Definition pyxis.cpp:440
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition pyxis.cpp:106
Pyxis()
Definition pyxis.cpp:49
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
Definition pyxis.cpp:57
const char * getDefaultName() override
Definition pyxis.cpp:101
virtual IPState MoveRotator(double angle) override
MoveRotator Go to specific angle.
Definition pyxis.cpp:461
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition pyxis.cpp:223
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition pyxis.cpp:246
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition pyxis.cpp:525
virtual bool ReverseRotator(bool enabled) override
ReverseRotator Reverse the direction of the rotator. CW is usually the normal direction,...
Definition pyxis.cpp:502
virtual bool Handshake() override
perform handshake with device to check communication
Definition pyxis.cpp:92
const char * INFO_TAB
INFO_TAB Where all the properties for general information 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
@ TTY_OVERFLOW
Definition indicom.h:62
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
Definition indidevapi.c:355
#define MAXRBUF
Definition indidriver.c:52
#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
uint8_t cmd[4]
Definition pwc-ioctl.h:2
#define PYRIX_CMD
Definition pyxis.cpp:33
#define PYXIS_2INCH_RATE
Definition pyxis.cpp:38
#define PYXIS_3INCH_RATE
Definition pyxis.cpp:37
#define POLL_100MS
Definition pyxis.cpp:45
#define PYXIS_3INCH_PER_DEG
Definition pyxis.cpp:41
#define PYXIS_2INCH_PER_DEG
Definition pyxis.cpp:42
#define PYXIS_TIMEOUT
Definition pyxis.cpp:31
#define PYRIX_BUF
Definition pyxis.cpp:32
std::unique_ptr< Pyxis > pyxis(new Pyxis())
#define SETTINGS_TAB
Definition robofocus.cpp:44
double round(double value, int decimal_places)