Instrument Neutral Distributed Interface INDI 2.2.5
rigel_dome.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Rigel Systems Dome INDI Driver
3
4 Copyright(c) 2019 Jasem Mutlaq. All rights reserved.
5
6 Based on Protocol extracted from https://github.com/rpineau/RigelDome
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License version 2 as published by the Free Software Foundation.
11 .
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16 .
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*******************************************************************************/
22
23#include "rigel_dome.h"
24#include "indicom.h"
26
27#include <cmath>
28#include <cstring>
29#include <regex>
30#include <memory>
31#include <termios.h>
32
33// We declare an auto pointer to RigelDome.
34static std::unique_ptr<RigelDome> rigelDome(new RigelDome());
35
36#define DOME_CMD 9 /* Dome command in bytes */
37#define DOME_BUF 16 /* Dome command buffer */
38#define DOME_TIMEOUT 3 /* 3 seconds comm timeout */
39
40#define SIM_SHUTTER_TIMER 5.0 /* Simulated Shutter closes/open in 5 seconds */
41#define SIM_FLAP_TIMER 5.0 /* Simulated Flap closes/open in 3 seconds */
42#define SIM_DOME_HI_SPEED 5.0 /* Simulated dome speed 5.0 degrees per second, constant */
43#define SIM_DOME_LO_SPEED 0.5 /* Simulated dome speed 0.5 degrees per second, constant */
44
55
57{
59
60 OperationSP[OPERATION_FIND_HOME].fill("OPERATION_FIND_HOME", "Find Home", ISS_OFF);
61 OperationSP[OPERATION_CALIBRATE].fill("OPERATION_CALIBRATE", "Calibrate", ISS_OFF);
62 OperationSP.fill(getDeviceName(), "OPERATION", "Operation", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
63
64 InfoTP[INFO_FIRMWARE].fill("FIRMWARE", "Version", "NA");
65 InfoTP[INFO_MODEL].fill("MODEL", "Model", "NA");
66 InfoTP[INFO_TICKS].fill("TICKS_PER_REV", "Ticks/Rev", "NA");
67 InfoTP[INFO_BATTERY].fill("BATTERY", "Battery", "NA");
68 InfoTP.fill(getDeviceName(), "FIRMWARE_INFO", "Info", INFO_TAB, IP_RO, 60, IPS_IDLE);
69
70 HomePositionNP[AXIS_AZ].fill("HOME_AZ", "AZ D:M:S", "%10.6m", 0.0, 360.0, 0.0, 0);
71 HomePositionNP.fill(getDeviceName(), "DOME_HOME_POSITION", "Home Position", SITE_TAB, IP_RW, 60, IPS_IDLE);
72
76
77 // Initialize Pulsar Dome Drive workaround variables
78 previousAngle = -1;
79 stuckAngleCounter = 0;
80
81 return true;
82}
83
84/************************************************************************************
85 *
86* ***********************************************************************************/
87bool RigelDome::getStartupValues()
88{
89 targetAz = 0;
90
91 InfoTP.setState((readFirmware() && readModel() && readStepsPerRevolution()) ? IPS_OK : IPS_ALERT);
92 if (HasShutter())
93 readBatteryLevels();
94 InfoTP.apply();
95
96 if (readPosition())
98
99 if (readShutterStatus())
101
102 if (readHomePosition())
103 HomePositionNP.apply();
104
105 if (InitPark())
106 {
107 // If loading parking data is successful, we just set the default parking values.
109 }
110 else
111 {
112 // Otherwise, we set all parking data to default in case no parking data is found.
113 SetAxis1Park(0);
115 }
116
117 return true;
118}
119
120/************************************************************************************
121 *
122* ***********************************************************************************/
124{
125 char res[DRIVER_LEN] = {0};
126 sendCommand("PULSAR", res); // send dummy command to flush serial line
127
128 bool rc = readShutterStatus();
129 if (rc)
130 {
131 if (m_rawShutterState != S_NotFitted)
133 }
134
135 return rc;
136}
137
138/************************************************************************************
139 *
140* ***********************************************************************************/
142{
143 return "Rigel Dome";
144}
145
146/************************************************************************************
147 *
148* ***********************************************************************************/
150{
152
153 if (isConnected())
154 {
155 defineProperty(OperationSP);
156 defineProperty(InfoTP);
157 defineProperty(HomePositionNP);
158
159 getStartupValues();
160 }
161 else
162 {
163 deleteProperty(OperationSP);
164 deleteProperty(InfoTP);
165 deleteProperty(HomePositionNP);
166 }
167
168 return true;
169}
170
171/************************************************************************************
172 *
173* ***********************************************************************************/
174bool RigelDome::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
175{
176 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
177 {
178 if (OperationSP.isNameMatch(name))
179 {
180 const char *requestedOperation = IUFindOnSwitchName(states, names, n);
181 if (OperationSP[OPERATION_FIND_HOME].isNameMatch(requestedOperation))
182 {
183 if (home())
184 {
185 OperationSP.reset();
186 OperationSP[OPERATION_FIND_HOME].s = ISS_ON;
187 OperationSP.setState(IPS_BUSY);
188 LOG_INFO("Dome is moving to home position...");
190 }
191 else
192 {
193 OperationSP.setState(IPS_ALERT);
194 }
195 }
196 else if (OperationSP[OPERATION_CALIBRATE].isNameMatch(requestedOperation))
197 {
198 if (calibrate())
199 {
200 OperationSP.reset();
201 OperationSP[OPERATION_CALIBRATE].s = ISS_ON;
202 OperationSP.setState(IPS_BUSY);
203 LOG_INFO("Dome is calibrating...");
205 }
206 else
207 {
208 OperationSP.setState(IPS_ALERT);
209 }
210 }
211
212 OperationSP.apply();
213 return true;
214 }
215 }
216
217 return INDI::Dome::ISNewSwitch(dev, name, states, names, n);
218}
219
220/************************************************************************************
221 *
222* ***********************************************************************************/
223bool RigelDome::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 (HomePositionNP.isNameMatch(name))
228 {
229 HomePositionNP.update(values, names, n);
230 HomePositionNP.setState(IPS_OK);
231 auto homeAz = HomePositionNP[AXIS_AZ].getValue();
232 setHome(homeAz);
233 LOGF_INFO("Setting home position to %3.1f", homeAz);
234 HomePositionNP.apply();
235 return true;
236 }
237 }
238
239 return INDI::Dome::ISNewNumber(dev, name, values, names, n);
240}
241
242/************************************************************************************
243 *
244* ***********************************************************************************/
246{
247 if (!isConnected())
248 return; // No need to reset timer if we are not connected anymore
249
250 readState();
251
252 bool isMoving = (m_rawMotorState != M_Idle && m_rawMotorState != M_MovingAtSideral);
253
254 /*
255 Pulsar Dome Drive workaround to fix issue where the motor seems to
256 be struggling as it tries to get to the final position.
257 This improved version tracks consecutive cycles with no angle change
258 and only stops the motor after multiple cycles.
259 */
260 double currentAngle = DomeAbsPosNP[0].getValue();
261
262 // Check if angle has changed within tolerance and stop if stuck for threshold
263 if (std::abs(currentAngle - previousAngle) < ANGLE_TOLERANCE && isMoving)
264 {
265 stuckAngleCounter++;
266
267 if (stuckAngleCounter >= STUCK_THRESHOLD)
268 {
269 stuckAngleCounter = 0;
270 char res[DRIVER_LEN] = {0};
271
272 if (sendCommand("STOP", res))
273 {
274 double diff = std::abs(targetAz - currentAngle);
275 // Account for wrap-around (e.g., target 1, current 359)
276 if (diff > 180)
277 diff = 360.0 - diff;
278
279 LOGF_INFO("Motor stopped after %d cycles with no movement. Current: %.3f°, Target: %.3f°, Difference: %.3f°",
280 STUCK_THRESHOLD, currentAngle, targetAz, diff);
283 return;
284 }
285 }
286 }
287 else
288 {
289 // Angle changed, reset counter
290 stuckAngleCounter = 0;
291 }
292
293 previousAngle = currentAngle;
294 /* END Pulsar Dome Drive workaround */
295
296 if (DomeAbsPosNP.getState() == IPS_BUSY && isMoving == false)
297 {
298 bool isHoming = (OperationSP.getState() == IPS_BUSY && OperationSP[OPERATION_FIND_HOME].getState() == ISS_ON);
299 bool isCalibrating = (OperationSP.getState() == IPS_BUSY && OperationSP[OPERATION_CALIBRATE].getState() == ISS_ON);
300
301 if (isHoming)
302 {
303 LOG_INFO("Dome completed homing...");
304 OperationSP.reset();
305 OperationSP.setState(IPS_OK);
306 OperationSP.apply();
308 }
309 else if (isCalibrating)
310 {
311 LOG_INFO("Dome completed calibration...");
312 OperationSP.reset();
313 OperationSP.setState(IPS_OK);
314 OperationSP.apply();
316 }
317 else if (getDomeState() == DOME_PARKING)
318 {
319 SetParked(true);
320 LOG_INFO("Dome is parked.");
321 }
322 else
323 {
324 LOGF_INFO("Dome reached requested azimuth: %.3f Degrees", DomeAbsPosNP[0].getValue());
326 }
327 }
328 else
329 {
330 if (DomeAbsPosNP.getState() != IPS_BUSY && isMoving)
332
334 }
335
336 if (HasShutter())
337 {
338 ShutterState newShutterState = parseShutterState(m_rawShutterState);
339 if (newShutterState != getShutterState())
340 {
341 setShutterState(newShutterState);
342 }
343
344 if (readBatteryLevels())
345 InfoTP.apply();
346 }
347
349}
350
355{
356 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
357
358 targetAz = az;
359 snprintf(cmd, DRIVER_LEN, "GO %3.1f", az);
360 if (sendCommand(cmd, res) == false)
361 return IPS_ALERT;
362
363 // Reset stuck counter for new movement
364 stuckAngleCounter = 0;
365
366 return (res[0] == 'A') ? IPS_BUSY : IPS_ALERT;
367}
368
373{
374 targetAz = range360(DomeAbsPosNP[0].getValue() + azDiff);
375 // It will take a few cycles to reach final position
376 return MoveAbs(targetAz);
377}
378
382bool RigelDome::Sync(double az)
383{
384 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
385
386 targetAz = az;
387 snprintf(cmd, DRIVER_LEN, "ANGLE K %3.1f", az);
388 if (sendCommand(cmd, res) == false)
389 return false;
390
391 return (res[0] == 'A');
392}
393
398{
399 if (readShutterStatus() && ShutterParkPolicySP[SHUTTER_CLOSE_ON_PARK].getState() == ISS_ON)
400 {
402 {
403 LOG_INFO("Shutter close on park");
404 }
405 else
406 return IPS_ALERT;
407 }
408
409 targetAz = GetAxis1Park();
410 if (setParkAz(targetAz))
411 {
412 // Reset stuck counter for parking movement
413 stuckAngleCounter = 0;
414
415 char res[DRIVER_LEN] = {0};
416 if (sendCommand("GO P", res) == false)
417 return IPS_ALERT;
418 return (res[0] == 'A' ? IPS_BUSY : IPS_ALERT);
419 }
420
421 return IPS_ALERT;
422}
423
427bool RigelDome::home()
428{
429 // Reset stuck counter for homing movement
430 stuckAngleCounter = 0;
431 targetAz = HomePositionNP[0].getValue();
432
433 char res[DRIVER_LEN] = {0};
434 if (sendCommand("GO H", res) == false)
435 return false;
436
437 return (res[0] == 'A');
438}
439
443bool RigelDome::calibrate()
444{
445 // Reset stuck counter for calibration movement
446 stuckAngleCounter = 0;
447
448 char res[DRIVER_LEN] = {0};
449 if (sendCommand("CALIBRATE", res) == false)
450 return false;
451
452 return (res[0] == 'A');
453}
454
458bool RigelDome::setHome(double az)
459{
460 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
461
462 targetAz = az;
463 snprintf(cmd, DRIVER_LEN, "HOME %3.1f", az);
464 if (sendCommand(cmd, res) == false)
465 return false;
466
467 return (res[0] == 'A');
468}
469
474{
475 if (readShutterStatus() && ShutterParkPolicySP[SHUTTER_OPEN_ON_UNPARK].getState() == ISS_ON)
476 {
478 {
479 LOG_INFO("Shutter open on unpark");
480 }
481 else
482 return IPS_ALERT;
483 }
484
485 return IPS_OK;
486}
487
492{
493 char res[DRIVER_LEN] = {0};
494
495 if (operation == SHUTTER_OPEN)
496 {
497 m_TargetShutter = operation;
498 sendCommand("OPEN", res);
499 }
500 else
501 {
502 m_TargetShutter = operation;
503 sendCommand("CLOSE", res);
504 }
505
506 return (res[0] == 'A') ? IPS_BUSY : IPS_ALERT;
507}
508
513{
514 if (sendCommand("STOP"))
515 {
516 // Reset stuck counter when aborting movement
517 stuckAngleCounter = 0;
518
519 if (OperationSP.getState() == IPS_BUSY)
520 {
521 LOGF_INFO("%s is aborted.", OperationSP[OPERATION_CALIBRATE].getState() == ISS_ON ? "Calibration" : "Finding home");
522 OperationSP.reset();
523 OperationSP.setState(IPS_ALERT);
524 OperationSP.apply();
525 }
526 else if (getShutterState() == SHUTTER_MOVING)
527 {
530 LOG_WARN("Shutter motion aborted!");
531 }
532 else
533 {
534 LOG_WARN("Dome motion aborted.");
535 }
536
537 return true;
538 }
539
540 return false;
541}
542
547{
548 SetAxis1Park(DomeAbsPosNP[0].getValue());
549 return true;
550}
551
556{
557 // By default set position to 90
558 SetAxis1Park(90);
559 return true;
560}
561
565bool RigelDome::setShutterConnected(bool enabled)
566{
567 char cmd[DRIVER_LEN] = {0};
568 snprintf(cmd, DRIVER_LEN, "BBOND %d", enabled ? 1 : 0);
569 return sendCommand(cmd);
570}
571
575bool RigelDome::isShutterConnected()
576{
577 char res[DRIVER_LEN] = {0};
578 if (sendCommand("BBOND", res) == false)
579 return false;
580 bool rc = (std::stoi(res) != 0);
581 LOGF_DEBUG("Shutter is %s.", (rc ? "connected" : "disconnected"));
582 return rc;
583}
584
588bool RigelDome::readStepsPerRevolution()
589{
590 char res[DRIVER_LEN] = {0};
591 if (sendCommand("ENCREV", res) == false)
592 return false;
593
594 InfoTP[INFO_TICKS].setText(res);
595 return true;
596}
597
601bool RigelDome::readBatteryLevels()
602{
603 char res[DRIVER_LEN] = {0};
604 if (sendCommand("BAT", res) == false)
605 return false;
606
607 int percent = 0;
608 double volts = 0;
609
610 if (sscanf(res, "%d %lf", &percent, &volts) != 2)
611 return false;
612
613 char levels[DRIVER_LEN] = {0};
614 snprintf(levels, DRIVER_LEN, "%.2fv (%d%%)", volts / 1000.0, percent);
615 InfoTP[INFO_BATTERY].setText(levels);
616 return true;
617}
618
622bool RigelDome::readPosition()
623{
624 char res[DRIVER_LEN] = {0};
625 if (sendCommand("ANGLE", res) == false)
626 return false;
627
628 DomeAbsPosNP[0].setValue(std::stod(res));
629 return true;
630}
631
632bool RigelDome::readHomePosition()
633{
634 char res[DRIVER_LEN] = {0};
635
636 if (sendCommand("HOME", res) == false)
637 return false;
638
639 HomePositionNP[0].setValue(std::stod(res));
640 return true;
641}
642
646bool RigelDome::setParkAz(double az)
647{
648 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
649
650 snprintf(cmd, DRIVER_LEN, "PARK %3.1f", az);
651 if (sendCommand(cmd, res) == false)
652 return false;
653
654 return res[0] == 'A';
655}
656
660bool RigelDome::readState()
661{
662 char res[DRIVER_LEN] = {0};
663 if (sendCommand("V", res) == false)
664 return false;
665
666 std::vector<std::string> fields = split(res, "\t");
667 if (fields.size() < 13)
668 return false;
669
670 DomeAbsPosNP[0].setValue(std::stod(fields[0]));
671 m_rawMotorState = static_cast<RigelMotorState>(std::stoi(fields[1]));
672 m_rawShutterState = static_cast<RigelShutterState>(std::stoi(fields[5]));
673 return true;
674}
675
679INDI::Dome::ShutterState RigelDome::parseShutterState(int state)
680{
681 switch (state)
682 {
683 case S_Open:
684 return SHUTTER_OPENED;
685
686 case S_Opening:
687 return SHUTTER_MOVING;
688
689 case S_Closed:
690 return SHUTTER_CLOSED;
691
692 case S_Closing:
693 return SHUTTER_MOVING;
694
695 case S_Error:
696 return SHUTTER_ERROR;
697
698 default:
699 return SHUTTER_UNKNOWN;
700 }
701}
705bool RigelDome::readShutterStatus()
706{
707 char res[DRIVER_LEN] = {0};
708 if (sendCommand("SHUTTER", res) == false)
709 return false;
710
711 m_rawShutterState = static_cast<RigelShutterState>(std::stoi(res));
712 return true;
713}
714
718bool RigelDome::readFirmware()
719{
720 char res[DRIVER_LEN] = {0};
721
722 if (sendCommand("VER", res) == false)
723 return false;
724
725 InfoTP[INFO_FIRMWARE].setText(res);
726 return true;
727}
728
732bool RigelDome::readModel()
733{
734 char res[DRIVER_LEN] = {0};
735
736 if (sendCommand("PULSAR", res) == false)
737 return false;
738
739 InfoTP[INFO_MODEL].setText(res);
740 return true;
741}
742
746bool RigelDome::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
747{
748 int nbytes_written = 0, nbytes_read = 0, rc = -1;
749
750 tcflush(PortFD, TCIOFLUSH);
751
752 if (cmd_len > 0)
753 {
754 char hex_cmd[DRIVER_LEN * 3] = {0};
755 hexDump(hex_cmd, cmd, cmd_len);
756 LOGF_DEBUG("CMD <%s>", hex_cmd);
757 rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
758 }
759 else
760 {
761 LOGF_DEBUG("CMD <%s>", cmd);
762
763 char formatted_command[DRIVER_LEN] = {0};
764 snprintf(formatted_command, DRIVER_LEN, "%s\r", cmd);
765 rc = tty_write_string(PortFD, formatted_command, &nbytes_written);
766 }
767
768 if (rc != TTY_OK)
769 {
770 char errstr[MAXRBUF] = {0};
771 tty_error_msg(rc, errstr, MAXRBUF);
772 LOGF_ERROR("Serial write error: %s.", errstr);
773 return false;
774 }
775
776 if (res == nullptr)
777 return true;
778
779 if (res_len > 0)
780 rc = tty_read(PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
781 else
782 rc = tty_nread_section(PortFD, res, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
783
784 if (rc != TTY_OK)
785 {
786 char errstr[MAXRBUF] = {0};
787 tty_error_msg(rc, errstr, MAXRBUF);
788 LOGF_ERROR("Serial read error: %s.", errstr);
789 return false;
790 }
791
792 if (res_len > 0)
793 {
794 char hex_res[DRIVER_LEN * 3] = {0};
795 hexDump(hex_res, res, res_len);
796 LOGF_DEBUG("RES <%s>", hex_res);
797 }
798 else
799 {
800 // Remove extra \r
801 res[nbytes_read - 1] = 0;
802 LOGF_DEBUG("RES <%s>", res);
803 }
804
805 tcflush(PortFD, TCIOFLUSH);
806
807 return true;
808}
809
813void RigelDome::hexDump(char * buf, const char * data, int size)
814{
815 for (int i = 0; i < size; i++)
816 sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
817
818 if (size > 0)
819 buf[3 * size - 1] = '\0';
820}
821
825std::vector<std::string> RigelDome::split(const std::string &input, const std::string &regex)
826{
827 // passing -1 as the submatch index parameter performs splitting
828 std::regex re(regex);
829 std::sregex_token_iterator
830 first{input.begin(), input.end(), re, -1},
831 last;
832 return {first, last};
833}
834
839{
840 double target;
841
842 if (operation == MOTION_START)
843 {
844 target = DomeAbsPosNP[0].getValue();
845 if(dir == DOME_CW)
846 {
847 target += 5;
848 }
849 else
850 {
851 target -= 5;
852 }
853
854 if(target < 0)
855 target += 360;
856 if(target >= 360)
857 target -= 360;
858 }
859 else
860 {
861 target = DomeAbsPosNP[0].getValue();
862 }
863
864 MoveAbs(target);
865
866 return ((operation == MOTION_START) ? IPS_BUSY : IPS_OK);
867
868}
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
bool isConnected() 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.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
void SetDomeCapability(uint32_t cap)
SetDomeCapability set the dome capabilities. All capabilities must be initialized.
INDI::PropertySwitch ShutterParkPolicySP
Definition indidome.h:566
@ SHUTTER_OPEN_ON_UNPARK
Definition indidome.h:570
@ SHUTTER_CLOSE_ON_PARK
Definition indidome.h:569
void SetAxis1Park(double value)
SetRAPark Set current AZ parking position. The data park file (stored in ~/.indi/ParkData....
void SetAxis1ParkDefault(double steps)
SetAxis1Park Set default AZ parking position.
ShutterOperation
Shutter operation command.
Definition indidome.h:114
@ SHUTTER_CLOSE
Definition indidome.h:116
DomeMotionCommand
Definition indidome.h:97
@ MOTION_START
Definition indidome.h:98
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
Definition indidome.cpp:105
@ DOME_CAN_PARK
Definition indidome.h:159
@ DOME_CAN_ABS_MOVE
Definition indidome.h:157
@ DOME_HAS_SHUTTER
Definition indidome.h:161
@ DOME_CAN_REL_MOVE
Definition indidome.h:158
@ DOME_CAN_ABORT
Definition indidome.h:156
@ DOME_CAN_SYNC
Definition indidome.h:160
double GetAxis1Park()
uint32_t GetDomeCapability() const
GetDomeCapability returns the capability of the dome.
Definition indidome.h:204
bool HasShutter()
Definition indidome.h:258
@ SHUTTER_ERROR
Definition indidome.h:151
@ SHUTTER_MOVING
Definition indidome.h:149
@ SHUTTER_UNKNOWN
Definition indidome.h:150
@ SHUTTER_OPENED
Definition indidome.h:147
@ SHUTTER_CLOSED
Definition indidome.h:148
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition indidome.cpp:284
INDI::PropertyNumber DomeAbsPosNP
Definition indidome.h:536
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition indidome.cpp:503
void setShutterState(const ShutterState &value)
void setDomeState(const DomeState &value)
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
Connection::Serial * serialConnection
Definition indidome.h:607
void SetParkDataType(DomeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
INDI::PropertySwitch DomeShutterSP
Definition indidome.h:546
ShutterState getShutterState() const
Definition indidome.h:291
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition indidome.cpp:394
DomeState getDomeState() const
Definition indidome.h:285
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
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)
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)
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
@ M_MovingAtSideral
Definition rigel_dome.h:30
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual IPState ControlShutter(ShutterOperation operation) override
Open or Close shutter.
virtual IPState UnPark() override
UnPark dome. The action of the Unpark command is dome specific, but it may include opening the shutte...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool Sync(double az) override
Sync sets the dome current azimuth as the supplied azimuth position.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual IPState Move(DomeDirection dir, DomeMotionCommand operation) override
Move the Dome in a particular direction.
virtual IPState MoveAbs(double az) override
Move the Dome to an absolute azimuth.
virtual bool Abort() override
Abort all dome motion.
virtual IPState Park() override
Goto Park Position. The park position is an absolute azimuth value.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual const char * getDefaultName() override
virtual IPState MoveRel(double azDiff) override
Move the Dome to an relative position.
virtual bool Handshake() override
perform handshake with device to check communication
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * SITE_TAB
SITE_TAB Where all site information setting 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
@ AXIS_AZ
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
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
Definition indicom.c:1321
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 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
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 LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_WARN(txt)
Definition indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#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