Instrument Neutral Distributed Interface INDI 2.2.5
nexdome_beaver.cpp
Go to the documentation of this file.
1/*
2 NexDome Beaver Controller
3
4 Copyright (C) 2021 Jasem Mutlaq ([email protected])
5 Modified 2021 Sifan Kahale ([email protected])
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21*/
22
23#include "nexdome_beaver.h"
24
25#include "indicom.h"
28
29#include <cmath>
30#include <cstring>
31#include <cassert>
32#include <memory>
33#include <regex>
34
35#include <termios.h>
36#include <unistd.h>
37#include "config.h"
38
39static std::unique_ptr<Beaver> dome(new Beaver());
40
48
50{
52
55
59 // Rotator status
60 RotatorStatusTP[0].fill("RSTATUS", "Status", "Idle");
61 RotatorStatusTP.fill(getDeviceName(), "ROTATORSTATUS", "Dome", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
62
63 // Shutter status
64 ShutterStatusTP[0].fill("SSTATUS", "Status", "Idle");
65 ShutterStatusTP.fill(getDeviceName(), "SHUTTERSTATUS", "Shutter", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
66
67 // Shutter Voltage
68 ShutterVoltsNP[0].fill("SHUTTERvolts", "Volts", "%.2f", 0.00, 15.00, 0.00, 0.00);
69 ShutterVoltsNP.fill(getDeviceName(), "SHUTTERVOLTS", "Shutter", MAIN_CONTROL_TAB, IP_RO, 60, IPS_OK);
70
71 // Rotator Home
72 GotoHomeSP[0].fill("ROTATOR_HOME_GOTO", "Home", ISS_OFF);
73 GotoHomeSP.fill(getDefaultName(), "ROTATOR_GOTO_Home", "Rotator", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
74
76 // Rototor settings tab
78
79 // Home position
80 HomePositionNP[0].fill("HOME_AZ", "AZ D:M:S", "%10.6m", 0.0, 360.0, 0.0, 0);
81 HomePositionNP.fill(getDeviceName(), "HOME_POSITION", "Home Position", SITE_TAB, IP_RW, 60, IPS_IDLE);
82
83 // Home set options
84 HomeOptionsSP[HOMECURRENT].fill("HOME_CURRENT", "Current", ISS_OFF);
85 HomeOptionsSP[HOMEDEFAULT].fill("HOME_DEFAULT", "Default (0)", ISS_OFF);
86 HomeOptionsSP.fill(getDeviceName(), "DOME_HOME_OPTION", "Home Options", SITE_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
87
88 // Rotator Calibrations
89 RotatorCalibrationSP[ROTATOR_HOME_FIND].fill("ROTATOR_HOME_FIND", "Find Home", ISS_OFF);
90 RotatorCalibrationSP[ROTATOR_HOME_MEASURE].fill("ROTATOR_HOME_MEASURE", "Measure Home", ISS_OFF);
91 RotatorCalibrationSP[ROTATOR_FULL_MEASURE].fill("ROTATOR_FULL_MEASURE", "Full Measurement", ISS_OFF);
92 RotatorCalibrationSP.fill(getDefaultName(), "ROTATOR_CALIBRATION", "Rotator", ROTATOR_TAB, IP_RW, ISR_ATMOST1, 60,
93 IPS_IDLE);
94
95 // Rotator Abort
96 RotatorAbortSP[0].fill("ROTATOR_ABORT", "Abort", ISS_OFF);
97 RotatorAbortSP.fill(getDefaultName(), "ROTATOR_ABORT", "Rotator", ROTATOR_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
98
99 // Rotator Settings
100 RotatorSettingsNP[ROTATOR_MAX_SPEED].fill("ROTATOR_MAX_SPEED", "Max Speed (m/s)", "%.f", 1, 1000, 10, 800);
101 RotatorSettingsNP[ROTATOR_MIN_SPEED].fill("ROTATOR_MIN_SPEED", "Min Speed (m/s)", "%.f", 1, 1000, 10, 400);
102 RotatorSettingsNP[ROTATOR_ACCELERATION].fill("ROTATOR_ACCELERATION", "Acceleration (m/s^2)", "%.f", 1, 1000, 10, 500);
103 RotatorSettingsNP[ROTATOR_TIMEOUT].fill("ROTATOR_TIMEOUT", "Timeout (s)", "%.f", 1, 1000, 10, 83);
104 RotatorSettingsNP.fill(getDeviceName(), "ROTATOR_SETTINGS", "Settings", ROTATOR_TAB, IP_RW, 60, IPS_IDLE);
105
107 // Shutter settings tab
109 // Shutter Home (calibrate, reset)
110 ShutterCalibrationSP[SHUTTER_HOME_FIND].fill("SHUTTER_HOME_FIND", "AutoCalibrate", ISS_OFF);
111 ShutterCalibrationSP.fill(getDeviceName(), "SHUTTER_CALIBRATION", "Shutter", SHUTTER_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
112
113 // Shutter Abort
114 ShutterAbortSP[0].fill("SHUTTER_ABORT", "Abort", ISS_OFF);
115 ShutterAbortSP.fill(getDeviceName(), "SHUTTER_ABORT", "Shutter", SHUTTER_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
116
117 // Shutter Settings
118 ShutterSettingsNP[SHUTTER_MAX_SPEED].fill("SHUTTER_MAX_SPEED", "Max Speed (m/s)", "%.f", 1, 1000, 10, 800);
119 ShutterSettingsNP[SHUTTER_MIN_SPEED].fill("SHUTTER_MIN_SPEED", "Min Speed (m/s)", "%.f", 1, 1000, 10, 400);
120 ShutterSettingsNP[SHUTTER_ACCELERATION].fill("SHUTTER_ACCELERATION", "Acceleration (m/s^2)", "%.f", 1, 1000, 10, 500);
121 ShutterSettingsNP[SHUTTER_SAFE_VOLTAGE].fill("SHUTTER_SAFE_VOLTAGE", "Safe Voltage", "%.1f", 10, 14, .5, 11);
122 ShutterSettingsNP.fill(getDeviceName(), "SHUTTER_SETTINGS", "Settings", SHUTTER_TAB, IP_RW, 60, IPS_IDLE);
123
124 ShutterSettingsTimeoutNP[0].fill("SHUTTER_TIMEOUT", "Timeout (s)", "%.f", 1, 1000, 10, 83);
125 ShutterSettingsTimeoutNP.fill(getDeviceName(), "SHUTTER_R_SETTINGS", "Settings", SHUTTER_TAB, IP_RO, 60, IPS_IDLE);
126
128 // INFO Tab
130 // Beaver Firmware Version
131 VersionTP[0].fill("CVERSION", "Controller", "");
132 VersionTP.fill(getDeviceName(), "DOME_FIRMWARE", "Version", CONNECTION_TAB, IP_RO, 0, IPS_IDLE);
133
135 // Communication
137 // NOTE need to figure out how to get network connection working
138 tcpConnection->setDefaultHost("192.168.1.1");
142 return true;
143}
144
146{
148
149 if (isConnected())
150 {
151 double curPark;
152 if (!sendCommand("!domerot getpark#", curPark))
153 return false;
154 if (InitPark())
155 {
156 SetAxis1ParkDefault(curPark);
157 }
158 else
159 {
160 SetAxis1Park(curPark);
161 SetAxis1ParkDefault(curPark);
162 }
163 TimerHit();
164
165 defineProperty(VersionTP);
166 defineProperty(HomePositionNP);
167 defineProperty(HomeOptionsSP);
168 defineProperty(RotatorCalibrationSP);
169 defineProperty(RotatorAbortSP);
170 defineProperty(GotoHomeSP);
171 defineProperty(RotatorSettingsNP);
172 defineProperty(RotatorStatusTP);
173 if (shutterOnLine())
174 {
175 defineProperty(ShutterCalibrationSP);
176 defineProperty(ShutterAbortSP);
177 defineProperty(ShutterSettingsNP);
178 defineProperty(ShutterSettingsTimeoutNP);
179 defineProperty(ShutterStatusTP);
180 defineProperty(ShutterVoltsNP);
181 }
182 }
183 else
184 {
185 deleteProperty(VersionTP.getName());
186 deleteProperty(RotatorCalibrationSP.getName());
187 deleteProperty(RotatorAbortSP.getName());
188 deleteProperty(GotoHomeSP.getName());
189 deleteProperty(HomePositionNP.getName());
190 deleteProperty(HomeOptionsSP.getName());
191 deleteProperty(RotatorSettingsNP.getName());
192 deleteProperty(ShutterSettingsTimeoutNP.getName());
193 deleteProperty(RotatorStatusTP.getName());
194 deleteProperty(ShutterCalibrationSP.getName());
195 deleteProperty(ShutterAbortSP.getName());
196 deleteProperty(ShutterSettingsNP.getName());
197 deleteProperty(ShutterStatusTP.getName());
198 deleteProperty(ShutterVoltsNP.getName());
199
200 }
201 return true;
202}
203
204
209{
210 // tty_generic_udp_format is a process-global flag in indicom.c: it must
211 // only be on while the active connection is really our UDP socket. Left
212 // on unconditionally (as it used to be, set once in initProperties()) it
213 // also hijacks the serial connection's tty_nread_section reads, which
214 // then do a single non-looping datagram-style read instead of accumulating
215 // bytes until the stop character, corrupting any reply that arrives
216 // split across more than one low-level USB-serial read.
218
219 if (echo())
220 {
221 // Check if shutter is online
222 if (shutterOnLine())
223 {
224 LOG_DEBUG("Shutter in online, enabling Dome has shutter property");
226 return true;
227 }
228 return true;
229 }
230
231 return false;
232}
233
238{
239 return "NexDome Beaver";
240}
241
245bool Beaver::echo()
246{
247 double res = 0;
248
249 // retrieve the controller version from the dome
250 char result[DRIVER_LEN] = {0};
251 if (!sendRawCommand("!seletek tversion#", result))
252 {
253 LOG_ERROR("Error getting version info");
254 return false;
255 }
256 std::string resString = result;
257 LOGF_DEBUG("Version string returned %s", resString.c_str());
258 std::regex e(R"(.*:\d*:(.*))");
259 std::sregex_iterator iter(resString.begin(), resString.end(), e);
260 if (iter == std::sregex_iterator())
261 {
262 LOGF_ERROR("Unexpected version response: %s", resString.c_str());
263 return false;
264 }
265 VersionTP[0].setText((*iter)[1]);
266
267 // retrieve the current az from the dome
268 if (rotatorGetAz())
269 LOGF_INFO("Dome reports az: %.1f", DomeAbsPosNP[0].getValue());
270 else
271 return false;
272
273 // retrieve the current home offset from the dome
274 if (!sendCommand("!domerot gethome#", res))
275 return false;
276 else
277 {
278 HomePositionNP[0].setValue(res);
279 LOGF_INFO("Dome reports home offset: %f", res);
280 }
281
282 // retrieve the current park position from the dome
283 if (!sendCommand("!domerot getpark#", res))
284 return false;
285 else
286 {
287 SetAxis1Park(res);
288 LOGF_INFO("Dome reports park: %.1f", res);
289 }
290
291 // get current rotator settings
292 if (!rotatorGetSettings())
293 return false;
294
295 // get current shutter settings
296 if (shutterOnLine())
297 {
298 if (!shutterGetSettings())
299 return false;
300 }
301 return true;
302}
303
307bool Beaver::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
308{
309 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
310 {
312 // Rotator Calibration (find and measure home)
314 if (RotatorCalibrationSP.isNameMatch(name))
315 {
316 bool wasMoving = getDomeState() == DOME_MOVING;
317 RotatorCalibrationSP.update(states, names, n);
318 bool rc = false;
319 switch (RotatorCalibrationSP.findOnSwitchIndex())
320 {
321 case ROTATOR_HOME_FIND:
322 rc = rotatorFindHome();
323 RotatorCalibrationSP.setState(rc ? IPS_BUSY : IPS_ALERT);
324 break;
325
326 case ROTATOR_HOME_MEASURE:
327 rc = rotatorMeasureHome();
328 RotatorCalibrationSP.setState(rc ? IPS_BUSY : IPS_ALERT);
329 break;
330
331 case ROTATOR_FULL_MEASURE:
332 rc = rotatorFullMeasure();
333 RotatorCalibrationSP.setState(rc ? IPS_BUSY : IPS_ALERT);
334 break;
335
336 default:
337 // Button toggled off while the dome was still moving: treat it as an abort request,
338 // otherwise the switch goes idle in the UI while the dome keeps calibrating regardless.
339 // Checked against actual dome motion (not just this property's state), since a rejected
340 // re-start attempt (dome already busy) leaves the property in IPS_ALERT, not IPS_BUSY.
341 if (wasMoving)
342 {
343 rc = abortAll();
344 RotatorCalibrationSP.setState(rc ? IPS_IDLE : IPS_ALERT);
345 }
346 break;
347 }
348 RotatorCalibrationSP.apply();
349 return true;
350 }
351
353 // Rotator Abort
355 if (RotatorAbortSP.isNameMatch(name))
356 {
357 RotatorAbortSP.update(states, names, n);
358 bool rc = rotatorAbort();
359 RotatorAbortSP.setState(rc ? IPS_OK : IPS_ALERT);
360 RotatorAbortSP.apply();
361 return true;
362 }
363
365 // Rotator Go Home
367 if (GotoHomeSP.isNameMatch(name))
368 {
369 GotoHomeSP.update(states, names, n);
370 bool rc = false;
371 rc = rotatorGotoHome();
372 GotoHomeSP.setState(rc ? IPS_BUSY : IPS_ALERT);
373 GotoHomeSP.apply();
374 return true;
375 }
376
378 // Home options
380 if (HomeOptionsSP.isNameMatch(name))
381 {
382 HomeOptionsSP.update(states, names, n);
383 bool rc = false;
384 double newAz, curHome;
385 switch (HomeOptionsSP.findOnSwitchIndex())
386 {
387 case HOMECURRENT:
388 if (!sendCommand("!domerot getpark#", curHome))
389 return false;
390 newAz = 360.0 - curHome + rotatorGetAz();
391 rc = rotatorSetHome(newAz);
392 LOGF_DEBUG("New home az %.1f (from 360 - %1f + %1f)", newAz, curHome, rotatorGetAz());
393 HomeOptionsSP.setState(rc ? IPS_BUSY : IPS_ALERT);
394 break;
395
396 case HOMEDEFAULT:
397 rc = rotatorSetHome(0.0);
398 HomeOptionsSP.setState(rc ? IPS_OK : IPS_ALERT);
399 break;
400 }
401 HomeOptionsSP.apply();
402 return true;
403 }
404
406 // Shutter Calibration
408 if (ShutterCalibrationSP.isNameMatch(name))
409 {
410 //TEST
411 ShutterCalibrationSP.update(states, names, n);
412 bool rc = shutterFindHome();
413 if (rc)
415 ShutterCalibrationSP.setState(rc ? IPS_BUSY : IPS_ALERT);
416 ShutterCalibrationSP.apply();
417 return true;
418 }
419
421 // Shutter Abort
423 if (ShutterAbortSP.isNameMatch(name))
424 {
425 ShutterAbortSP.update(states, names, n);
426 bool rc = shutterAbort();
427 ShutterAbortSP.setState(rc ? IPS_OK : IPS_ALERT);
428 ShutterAbortSP.apply();
429 return true;
430 }
431 }
432
433 return INDI::Dome::ISNewSwitch(dev, name, states, names, n);
434}
435
439bool Beaver::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
440{
441 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
442 {
444 // Rotator Settings
446 if (RotatorSettingsNP.isNameMatch(name))
447 {
448 RotatorSettingsNP.update(values, names, n);
449 RotatorSettingsNP.setState(rotatorSetSettings(RotatorSettingsNP[ROTATOR_MAX_SPEED].getValue(),
450 RotatorSettingsNP[ROTATOR_MIN_SPEED].getValue(),
451 RotatorSettingsNP[ROTATOR_ACCELERATION].getValue(),
452 RotatorSettingsNP[ROTATOR_TIMEOUT].getValue()
453 ) ? IPS_OK : IPS_ALERT);
454 RotatorSettingsNP.apply();
455 return true;
456 }
457
459 // Shutter Settings
461 if (ShutterSettingsNP.isNameMatch(name))
462 {
463 ShutterSettingsNP.update(values, names, n);
464 ShutterSettingsNP.setState(shutterSetSettings(ShutterSettingsNP[SHUTTER_MAX_SPEED].getValue(),
465 ShutterSettingsNP[SHUTTER_MIN_SPEED].getValue(),
466 ShutterSettingsNP[SHUTTER_ACCELERATION].getValue(),
467 ShutterSettingsNP[SHUTTER_SAFE_VOLTAGE].getValue()
468 ) ? IPS_OK : IPS_ALERT);
469 ShutterSettingsNP.apply();
470 return true;
471 }
472
476 if (HomePositionNP.isNameMatch(name))
477 {
478 HomePositionNP.update(values, names, n);
479 if (rotatorSetHome(HomePositionNP[0].getValue()))
480 {
481 HomePositionNP.apply();
482 return true;
483 }
484 else
485 return false;
486 }
487
491 if (ParkPositionNP.isNameMatch(name))
492 {
493 ParkPositionNP.update(values, names, n);
494 if (rotatorSetPark(ParkPositionNP[AXIS_RA].getValue()))
495 {
499 return true;
500 }
501 else
502 return false;
503 }
504
505 }
506
507 return INDI::Dome::ISNewNumber(dev, name, values, names, n);
508
509}
510
515{
516 if (!isConnected())
517 {
518 return;
519 }
520
521 // Get Position and sets az pos field
522 rotatorGetAz();
523 LOGF_DEBUG("Rotator position: %f", DomeAbsPosNP[0].getValue());
524
525 // Query rotator status
526 uint16_t domeStatus = 0;
527 if (!getDomeStatus(domeStatus))
528 {
529 LOG_ERROR("Could not get dome status");
530 }
531
533 // Test for general dome errors
535 if (domeStatus & DOME_STATUS_UNSAFE_CW)
536 {
537 LOG_ERROR("CW Unsafe Error");
539 RotatorStatusTP.apply();
540 }
541 if (domeStatus & DOME_STATUS_UNSAFE_RG)
542 {
543 LOG_ERROR("RGx Unsafe Error");
545 RotatorStatusTP.apply();
546 }
547
549 // Test rotator and set status
551
552 // Is rotator idle?
553 if (!(domeStatus & DOME_STATUS_ROTATOR_MOVING))
554 {
555
556 // Dome Parked
557 if (rotatorIsParked() && (getDomeState() == DOME_PARKING))
558 {
559 SetParked(true);
560 std::string rStatus = "Parked";
561 RotatorStatusTP[0].setText(rStatus);
562 RotatorStatusTP.setState(IPS_OK);
563 LOG_DEBUG("Dome is parked.");
564 }
565 // Measuring Home completed
566 else if (!strcmp(RotatorStatusTP[0].getText(), "Measuring Home"))
567 {
569 RotatorCalibrationSP.setState(IPS_OK);
570 RotatorCalibrationSP.apply();
571 std::string rStatus = "Home";
572 RotatorStatusTP[0].setText(rStatus);
573 RotatorStatusTP.setState(IPS_OK);
574 }
575 // Finding Home completed
576 else if (!strcmp(RotatorStatusTP[0].getText(), "Finding Home"))
577 {
579 RotatorCalibrationSP.setState(IPS_OK);
580 RotatorCalibrationSP.apply();
581 std::string rStatus = "Home";
582 RotatorStatusTP[0].setText(rStatus);
583 RotatorStatusTP.setState(IPS_OK);
584 }
585 // Full dome measurement completed
586 else if (!strcmp(RotatorStatusTP[0].getText(), "Measuring Full Dome"))
587 {
589 RotatorCalibrationSP.setState(IPS_OK);
590 RotatorCalibrationSP.apply();
591 std::string rStatus = "Home";
592 RotatorStatusTP[0].setText(rStatus);
593 RotatorStatusTP.setState(IPS_OK);
594 }
595 // Homing completed
596 else if (!strcmp(RotatorStatusTP[0].getText(), "Homing"))
597 {
599 std::string rStatus = "Home";
600 RotatorStatusTP[0].setText(rStatus);
601 RotatorStatusTP.setState(IPS_OK);
602 GotoHomeSP.setState(IPS_OK);
603 GotoHomeSP.apply();
604 LOG_DEBUG("Dome at home");
605 }
606 // Move completed
607 else if (getDomeState() == DOME_MOVING)
608 {
609 RotatorStatusTP.apply();
611 RotatorCalibrationSP.setState(IPS_OK);
612 RotatorCalibrationSP.apply();
613 std::string rStatus = "Idle";
614 RotatorStatusTP[0].setText(rStatus);
615 RotatorStatusTP.setState(IPS_OK);
616 LOG_DEBUG("Dome reached target position.");
617 }
618 RotatorStatusTP.apply();
619 }
620
622 // Test Shutter and set status
624 if (shutterOnLine())
625 {
626
627 // Test for shutter error
628 if (domeStatus & DOME_STATUS_SHUTTER_ERROR)
629 {
630 LOG_ERROR("Shutter Mechanical Error");
631 std::string rStatus = "Mechanical Error";
632 ShutterStatusTP[0].setText(rStatus);
633 ShutterStatusTP.apply();
635 }
636
637 // If moving, set status
639 {
640
641 if (domeStatus & DOME_STATUS_SHUTTER_OPENING)
642 {
644 std::string rStatus = "Opening";
645 ShutterStatusTP[0].setText(rStatus);
646 LOG_DEBUG("Shutter state set to Opening");
647 }
648 else if (domeStatus & DOME_STATUS_SHUTTER_CLOSING)
649 {
651 std::string rStatus = "Closing";
652 ShutterStatusTP[0].setText(rStatus);
653 LOG_DEBUG("Shutter state set to Closing");
654 }
655 else if (domeStatus & DOME_STATUS_SHUTTER_MOVING)
656 {
658 std::string rStatus = "Moving";
659 ShutterStatusTP[0].setText(rStatus);
660 LOG_DEBUG("Shutter is moving");
661 }
662
663 }
664
665 // if stopped, test if opened or closed
666 if (domeStatus & DOME_STATUS_SHUTTER_OPENED)
667 {
669 std::string rStatus = "Open";
670 ShutterStatusTP[0].setText(rStatus);
671 LOG_DEBUG("Shutter state set to OPEN");
672 }
673 if (domeStatus & DOME_STATUS_SHUTTER_CLOSED)
674 {
676 std::string rStatus = "Closed";
677 ShutterStatusTP[0].setText(rStatus);
678 LOG_DEBUG("Shutter state set to CLOSED");
679 }
680 ShutterStatusTP.apply();
681
682 // Update shutter voltage
683 double res;
684 // ignoring a random get voltage cmd error here and just reporting successful status
685 if (sendCommand("!dome getshutterbatvoltage#", res))
686 {
687 LOGF_DEBUG("Shutter voltage currently is: %.2f", res);
688 ShutterVoltsNP[0].setValue(res);
689 (res < ShutterSettingsNP[SHUTTER_SAFE_VOLTAGE].getValue()) ? ShutterVoltsNP.setState(IPS_ALERT) : ShutterVoltsNP.setState(
690 IPS_OK);
691 ShutterVoltsNP.apply();
692 }
693 }
694
696}
697
702{
703 if (rotatorGotoAz(az))
704 {
705 m_TargetRotatorAz = az;
707 std::string rStatus = "Moving";
708 RotatorStatusTP[0].setText(rStatus);
709 RotatorStatusTP.apply();
710 return IPS_BUSY;
711 }
712 return IPS_ALERT;
713}
714
719{
720 azDiff = domeDir * azDiff;
721 m_TargetRotatorAz = range360(DomeAbsPosNP[0].getValue() + azDiff);
722 LOGF_DEBUG("Requested rel move of %.1f", azDiff);
723 lastAzDiff = fabs(azDiff);
724 return MoveAbs(m_TargetRotatorAz);
725}
726
731{
732 LOG_DEBUG("Re-implemented move was called");
733 if (operation == MOTION_START)
734 {
735 if (dir == DOME_CW)
736 {
737 domeDir = 1;
738 }
739 else
740 {
741 domeDir = -1;
742 }
743 MoveRel(lastAzDiff);
744
745 }
746 return IPS_OK;
747}
748
753{
754 double res = 0;
755 if (operation == SHUTTER_OPEN)
756 {
757 if (sendCommand("!dome openshutter#", res))
758 {
759 std::string rStatus = "Opening";
760 ShutterStatusTP[0].setText(rStatus);
761 ShutterStatusTP.apply();
763 return IPS_BUSY;
764 }
765 else
766 return IPS_ALERT;
767 }
768 else if (operation == SHUTTER_CLOSE)
769 {
770 if (sendCommand("!dome closeshutter#", res))
771 {
772 std::string rStatus = "Shutting";
773 ShutterStatusTP[0].setText(rStatus);
774 ShutterStatusTP.apply();
776 return IPS_BUSY;
777 }
778 else
779 return IPS_ALERT;
780 }
781 return IPS_ALERT;
782}
783
788{
790 return true;
791}
792
796bool Beaver::rotatorGotoAz(double az)
797{
798 char cmd[DRIVER_LEN] = {0};
799 double res = 0;
800 snprintf(cmd, DRIVER_LEN, "!dome gotoaz %.2f#", az);
802 std::string rStatus = "Moving";
803 RotatorStatusTP[0].setText(rStatus);
804 RotatorStatusTP.apply();
805 return sendCommand(cmd, res);
806}
807
811bool Beaver::rotatorGetAz()
812{
813 double res = 0;
814 if (sendCommand("!dome getaz#", res))
815 {
816 DomeAbsPosNP[0].setValue(res);
818 return true;
819 }
820 return false;
821}
822
826bool Beaver::rotatorSetHome(double az)
827{
828 char cmd[DRIVER_LEN] = {0};
829 double res = 0;
830 snprintf(cmd, DRIVER_LEN, "!domerot sethome %.2f#", az);
831 if (sendCommand(cmd, res))
832 {
833 LOGF_INFO("Home is set to: %.1f", az);
834 return true;
835 }
836 return false;
837}
838
843{
844 double res;
845 if (sendCommand("!dome gopark#", res))
846 {
847 std::string rStatus = "Parking";
848 RotatorStatusTP[0].setText(rStatus);
849 RotatorStatusTP.apply();
850 // check shutter policy
851 if (shutterOnLine() && (ShutterParkPolicySP[SHUTTER_CLOSE_ON_PARK].getState() == ISS_ON))
852 {
854 {
857 }
858 else
859 return IPS_ALERT;
860 }
861 return IPS_BUSY;
862 }
863 return IPS_ALERT;
864}
865
870{
871 std::string rStatus = "unParked";
872 RotatorStatusTP[0].setText(rStatus);
873 RotatorStatusTP.apply();
874 // check shutter policy
875 if (shutterOnLine() && (ShutterParkPolicySP[SHUTTER_OPEN_ON_UNPARK].getState() == ISS_ON))
876 {
878 {
881 }
882 else
883 return IPS_ALERT;
884 }
885 return IPS_OK;
886}
887
891bool Beaver::rotatorSetPark(double az)
892{
893 double res = 0;
894 char cmd[DRIVER_LEN] = {0};
895 snprintf(cmd, DRIVER_LEN, "!domerot setpark %.2f#", az);
896 if (sendCommand(cmd, res))
897 {
898 LOGF_INFO("Park set to: %.2f", az);
899 SetAxis1Park(az);
900 return true;
901 }
902
903 return false;
904}
905
910{
911 double res = 0;
912 char cmd[DRIVER_LEN] = {0};
913 snprintf(cmd, DRIVER_LEN, "!domerot setpark %.2f#", DomeAbsPosNP[0].getValue());
914 if (sendCommand(cmd, res))
915 {
916 SetAxis1Park(DomeAbsPosNP[0].getValue());
917 LOGF_INFO("Park set to current: %.2f", DomeAbsPosNP[0].getValue());
918 }
919 return true;
920
921 return false;
922}
923
928{
929 double res = 0;
930 char cmd[DRIVER_LEN] = {0};
931 snprintf(cmd, DRIVER_LEN, "!domerot setpark %d#", 0);
932 if (sendCommand(cmd, res))
933 {
934 SetAxis1Park(0.0);
935 LOG_INFO("Park set to default: 0.00");
936 return true;
937 }
938
939 return false;
940}
941
942
946bool Beaver::rotatorGotoHome()
947{
948 double res = 0;
949 if (sendCommand("!dome gohome#", res))
950 {
952 std::string rStatus = "Homing";
953 RotatorStatusTP[0].setText(rStatus);
954 RotatorStatusTP.apply();
955 return true;
956 }
957 return false;
958}
959
963bool Beaver::rotatorMeasureHome()
964{
965 double res = 0;
966 if (sendCommand("!dome autocalrot 1#", res))
967 {
968 if (res < 0)
969 {
970 LOGF_ERROR("Rotator refused to start measuring home, error code: %.0f", res);
971 return false;
972 }
974 std::string rStatus = "Measuring Home";
975 RotatorStatusTP[0].setText(rStatus);
976 RotatorStatusTP.apply();
977 return true;
978 }
979 return false;
980}
981
985bool Beaver::rotatorFindHome()
986{
987 double res = 0;
988 if (sendCommand("!dome autocalrot 0#", res))
989 {
990 if (res < 0)
991 {
992 LOGF_ERROR("Rotator refused to start finding home, error code: %.0f", res);
993 return false;
994 }
996 std::string rStatus = "Finding Home";
997 RotatorStatusTP[0].setText(rStatus);
998 RotatorStatusTP.apply();
999 return true;
1000 }
1001 return false;
1002}
1003
1008bool Beaver::rotatorFullMeasure()
1009{
1010 double res = 0;
1011 if (sendCommand("!dome autocalrot 2#", res))
1012 {
1013 if (res < 0)
1014 {
1015 LOGF_ERROR("Rotator refused to start full measurement, error code: %.0f", res);
1016 return false;
1017 }
1019 std::string rStatus = "Measuring Full Dome";
1020 RotatorStatusTP[0].setText(rStatus);
1021 RotatorStatusTP.apply();
1022 return true;
1023 }
1024 return false;
1025}
1026
1030bool Beaver::rotatorIsHome()
1031{
1032 double status = 0;
1033 if (sendCommand("!dome athome#", status))
1034 {
1035 LOG_ERROR("Error checking home");
1036 return false;
1037 }
1038 LOGF_DEBUG("Rotator Home? %s", (status == 1) ? "true" : "false");
1039 if (status == 1)
1040 return true;
1041 else
1042 return false;
1043}
1044
1045
1049bool Beaver::rotatorIsParked()
1050{
1051 double status = 0;
1052 if (!sendCommand("!dome atpark#", status))
1053 {
1054 LOG_ERROR("Error checking park");
1055 return false;
1056 }
1057 LOGF_DEBUG("Rotator Parked? %s", (status == 1) ? "true" : "false");
1058 if (status == 1)
1059 return true;
1060 else
1061 return false;
1062}
1063
1067bool Beaver::getDomeStatus(uint16_t &domeStatus)
1068{
1069 double res = 0;
1070 if (!sendCommand("!dome status#", res))
1071 {
1072 LOG_ERROR("Status cmd errored out");
1073 return false;
1074 }
1075 domeStatus = static_cast<uint16_t>(res);
1076 LOGF_DEBUG("Dome status: %0x", domeStatus);
1077 return true;
1078}
1079
1083bool Beaver::shutterOnLine()
1084{
1085 double res = 0;
1086 uint16_t domeStatus;
1087 bool shutterIsUp = false;
1088 // retrieving shutter status
1089 if (!sendCommand("!dome shutterisup#", res))
1090 {
1091 LOG_ERROR("Shutter status cmd errored out");
1092 //failsave, return false/not online
1093 return false;
1094 }
1095 // retrieving comm status
1096 shutterIsUp = static_cast<bool>(res);
1097 if (!getDomeStatus(domeStatus))
1098 {
1099 LOG_ERROR("Shutter status cmd errored out");
1100 //failsave, return false/not online
1101 return false;
1102 }
1103 LOGF_DEBUG("ShutterIsUp %s Comms error %s", shutterIsUp ? "true" : "false",
1104 (domeStatus & DOME_STATUS_SHUTTER_COMM) ? "true" : "false");
1105 bool status = (shutterIsUp | !(domeStatus & DOME_STATUS_SHUTTER_COMM));
1106 LOGF_DEBUG("ShuttOnLine %s", status ? "true" : "false");
1107 return status;
1108}
1109
1114{
1115 return abortAll();
1116}
1117
1121bool Beaver::abortAll()
1122{
1123 double res = 0;
1124 if (sendCommand("!dome abort 1 1 1#", res))
1125 {
1126 std::string rStatus = "Idle";
1127 RotatorStatusTP[0].setText(rStatus);
1128 RotatorStatusTP.apply();
1129 if (!rotatorGetAz())
1130 return false;
1131 return true;
1132 }
1133
1134 return false;
1135}
1136
1140bool Beaver::rotatorAbort()
1141{
1142 double res = 0;
1143 if (sendCommand("!dome abort 0 1#", res))
1144 {
1145 std::string rStatus = "Idle";
1146 RotatorStatusTP[0].setText(rStatus);
1147 RotatorStatusTP.apply();
1148 if (!rotatorGetAz())
1149 return false;
1150 return true;
1151 }
1152
1153 return false;
1154}
1155
1159bool Beaver::shutterAbort()
1160{
1161 double res = 0;
1162 return sendCommand("!dome abort 0 0 1#", res);
1163}
1164
1168bool Beaver::shutterSetSettings(double maxSpeed, double minSpeed, double acceleration, double voltage)
1169{
1170 if (shutterOnLine())
1171 {
1172 char cmd[DRIVER_LEN] = {0};
1173 double res;
1174
1175 snprintf(cmd, DRIVER_LEN, "!dome setshuttermaxspeed %.2f#", maxSpeed);
1176 if (!sendCommand(cmd, res))
1177 {
1178 LOG_ERROR("Problem setting shutter max speed");
1179 return false;
1180 }
1181 snprintf(cmd, DRIVER_LEN, "!dome setshutterminspeed %.2f#", minSpeed);
1182 if (!sendCommand(cmd, res))
1183 {
1184 LOG_ERROR("Problem setting shutter min speed");
1185 return false;
1186 }
1187 snprintf(cmd, DRIVER_LEN, "!dome setshutteracceleration %.2f#", acceleration);
1188 if (!sendCommand(cmd, res))
1189 {
1190 LOG_ERROR("Problem setting shutter acceleration");
1191 return false;
1192 }
1193 snprintf(cmd, DRIVER_LEN, "!dome setshuttersafevoltage %.2f#", voltage);
1194 if (!sendCommand(cmd, res))
1195 {
1196 LOG_ERROR("Problem setting shutter safe voltage");
1197 return false;
1198 }
1199 if(!sendCommand("!seletek savefs#", res))
1200 {
1201 LOG_ERROR("Problem setting shutter savefs");
1202 return false;
1203 }
1204 LOG_INFO("Shutter parameters have been updated");
1205 }
1206
1207 return true;
1208}
1209
1213bool Beaver::shutterGetSettings()
1214{
1215 double res;
1216 if (shutterOnLine())
1217 {
1218 if (!sendCommand("!dome getshuttermaxspeed#", res))
1219 {
1220 LOG_ERROR("Problem getting shutter max speed");
1221 return false;
1222 }
1223 else
1224 {
1225 ShutterSettingsNP[SHUTTER_MAX_SPEED].setValue(res);
1226 LOGF_DEBUG("Shutter reports max speed of: %.1f", res);
1227 }
1228 if (!sendCommand("!dome getshutterminspeed#", res))
1229 {
1230 LOG_ERROR("Problem getting shutter min speed");
1231 return false;
1232 }
1233 else
1234 {
1235 ShutterSettingsNP[SHUTTER_MIN_SPEED].setValue(res);
1236 LOGF_DEBUG("Shutter reports min speed of: %.1f", res);
1237 }
1238 if (!sendCommand("!dome getshutteracceleration#", res))
1239 {
1240 LOG_ERROR("Problem getting shutter acceleration");
1241 return false;
1242 }
1243 else
1244 {
1245 ShutterSettingsNP[SHUTTER_ACCELERATION].setValue(res);
1246 LOGF_DEBUG("Shutter reports acceleration of: %.1f", res);
1247 }
1248 if (!sendCommand("!dome getshuttertimeoutopenclose#", res))
1249 {
1250 LOG_ERROR("Problem getting shutter timeout");
1251 return false;
1252 }
1253 else
1254 {
1255 ShutterSettingsTimeoutNP[0].setValue(res);
1256 LOGF_DEBUG("Shutter reports safe timeout of: %.1f", res);
1257 }
1258 if (!sendCommand("!dome getshuttersafevoltage#", res))
1259 {
1260 LOG_ERROR("Problem getting shutter safe voltage");
1261 return false;
1262 }
1263 else
1264 {
1265 ShutterSettingsNP[SHUTTER_SAFE_VOLTAGE].setValue(res);
1266 LOGF_DEBUG("Shutter reports safe voltage of: %.1f", res);
1267 }
1268 ShutterSettingsNP.apply();
1269 }
1270
1271 return true;
1272}
1273
1277bool Beaver::rotatorSetSettings(double maxSpeed, double minSpeed, double acceleration, double timeout)
1278{
1279 char cmd[DRIVER_LEN] = {0};
1280 double res;
1281
1282 snprintf(cmd, DRIVER_LEN, "!domerot setmaxspeed %.2f#", maxSpeed);
1283 if (!sendCommand(cmd, res))
1284 {
1285 LOG_ERROR("Problem setting rotator max speed");
1286 return false;
1287 }
1288 snprintf(cmd, DRIVER_LEN, "!domerot setminspeed %.2f#", minSpeed);
1289 if (!sendCommand(cmd, res))
1290 {
1291 LOG_ERROR("Problem setting rotator min speed");
1292 return false;
1293 }
1294 snprintf(cmd, DRIVER_LEN, "!domerot setacceleration %.2f#", acceleration);
1295 if (!sendCommand(cmd, res))
1296 {
1297 LOG_ERROR("Problem setting rotator acceleration");
1298 return false;
1299 }
1300 snprintf(cmd, DRIVER_LEN, "!domerot setmaxfullrotsecs %.2f#", timeout);
1301 if (!sendCommand(cmd, res))
1302 {
1303 LOG_ERROR("Problem setting rotator full rot secs");
1304 return false;
1305 }
1306 if(!sendCommand("!seletek savefs#", res))
1307 {
1308 LOG_ERROR("dome could not savefs");
1309 return false;
1310 }
1311 LOG_INFO("Rotator parameters have been updated");
1312
1313 return true;
1314}
1315
1319bool Beaver::rotatorGetSettings()
1320{
1321 double res;
1322 if (!sendCommand("!domerot getmaxspeed#", res))
1323 {
1324 LOG_ERROR("Problem getting rotator max speed");
1325 return false;
1326 }
1327 else
1328 {
1329 RotatorSettingsNP[ROTATOR_MAX_SPEED].setValue(res);
1330 LOGF_DEBUG("Rotator reports max speed of: %.1f", res);
1331 }
1332 if (!sendCommand("!domerot getminspeed#", res))
1333 {
1334 LOG_ERROR("Problem getting rotator min speed");
1335 return false;
1336 }
1337 else
1338 {
1339 RotatorSettingsNP[ROTATOR_MIN_SPEED].setValue(res);
1340 LOGF_DEBUG("Rotator reports min speed of: %.1f", res);
1341 }
1342 if (!sendCommand("!domerot getacceleration#", res))
1343 {
1344 LOG_ERROR("Problem getting rotator acceleration");
1345 return false;
1346 }
1347 else
1348 {
1349 RotatorSettingsNP[ROTATOR_ACCELERATION].setValue(res);
1350 LOGF_DEBUG("Rotator reports acceleration of: %.1f", res);
1351 }
1352 if (!sendCommand("!domerot getmaxfullrotsecs#", res))
1353 {
1354 LOG_ERROR("Problem getting rotator full rot secs");
1355 return false;
1356 }
1357 else
1358 {
1359 RotatorSettingsNP[ROTATOR_TIMEOUT].setValue(res);
1360 LOGF_DEBUG("Rotator reports timeout(s) of: %.1f", res);
1361 }
1362 RotatorSettingsNP.apply();
1363
1364 return true;
1365}
1366
1370bool Beaver::shutterFindHome()
1371{
1372 if (shutterOnLine())
1373 {
1374 double res = 0;
1375 return sendCommand("!dome autocalshutter#", res);
1376 }
1377 return false;
1378}
1379
1383bool Beaver::sendRawCommand(const char * cmd, char * response)
1384{
1385 int rc = TTY_OK;
1386 for (int i = 0; i < 3; i++)
1387 {
1388 int nbytes_written = 0, nbytes_read = 0;
1389 rc = tty_write_string(PortFD, cmd, &nbytes_written);
1390
1391 if (rc != TTY_OK)
1392 {
1393 char errstr[MAXRBUF] = {0};
1394 tty_error_msg(rc, errstr, MAXRBUF);
1395 LOGF_ERROR("Serial write error: %s.", errstr);
1396 return false;
1397 }
1398
1399 rc = tty_nread_section(PortFD, response, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
1400
1401 if (rc != TTY_OK)
1402 {
1403 // Response didn't arrive whole
1404 // Drop whatever is still pending before resending, otherwise the next
1405 // read picks up the tail of this reply and misreads it as the
1406 // answer to the retry.
1407 tcflush(PortFD, TCIFLUSH);
1408 usleep(100000);
1409 continue;
1410 }
1411
1412 // Remove extra #
1413 response[nbytes_read - 1] = 0;
1414 LOGF_DEBUG("Command Response: %s", response);
1415 return true;
1416 }
1417
1418 // timeouts used up, return error
1419 if (rc != TTY_OK)
1420 {
1421 char errstr[MAXRBUF] = {0};
1422 tty_error_msg(rc, errstr, MAXRBUF);
1423 LOGF_ERROR("Serial read error: %s.", errstr);
1424 }
1425 return false;
1426}
1430bool Beaver::sendCommand(const char * cmd, double &res)
1431{
1432 char response[DRIVER_LEN] = {0};
1433 sendRawCommand(cmd, response);
1434
1435 std::regex rgx(R"(.*:((-*\d+(\.\d*)*)))");
1436 std::smatch match;
1437 std::string input(response);
1438
1439 if (std::regex_search(input, match, rgx))
1440 {
1441 try
1442 {
1443 res = std::stof(match.str(1));
1444 return true;
1445 }
1446 catch (...)
1447 {
1448 LOGF_ERROR("Failed to process response: %s.", response);
1449 return false;
1450 }
1451 }
1452 LOGF_DEBUG("Command error: %s response: %d", cmd, response);
1453 return false;
1454}
@ DOME_STATUS_SHUTTER_CLOSING
@ DOME_STATUS_SHUTTER_COMM
@ DOME_STATUS_SHUTTER_OPENED
@ DOME_STATUS_UNSAFE_RG
@ DOME_STATUS_SHUTTER_CLOSED
@ DOME_STATUS_ROTATOR_MOVING
@ DOME_STATUS_SHUTTER_MOVING
@ DOME_STATUS_SHUTTER_OPENING
@ DOME_STATUS_SHUTTER_ERROR
@ DOME_STATUS_UNSAFE_CW
virtual IPState UnPark() override
Rotator unpark.
virtual IPState ControlShutter(ShutterOperation operation) override
open or close the shutter (will not show if shutter is not present)
virtual IPState Move(DomeDirection dir, DomeMotionCommand operation) override
Rotator move (calc's offset and calles abs move)
virtual IPState MoveRel(double azDiff) override
Rotator relative move (calc's offset and calles abs move)
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual IPState Park() override
Rotator park.
virtual bool SetCurrentPark() override
Rotator set park position to current.
virtual void TimerHit() override
Timer hit - update appropriate fields.
virtual bool SetDefaultPark() override
Rotator set park position to default (0 az)
virtual bool Abort() override
abort everything
const char * getDefaultName() override
Set default name.
bool Handshake() override
Handshake.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual IPState MoveAbs(double az) override
Rotator absolute move.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Number field updated.
virtual bool saveConfigItems(FILE *fp) override
INDI save config.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Switch field updated.
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
void setDefaultHost(const char *addressHost)
void setConnectionType(int type)
TODO should be renamed to setDefaultConnectionType.
void setDefaultPort(uint32_t addressPort)
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.
Connection::Interface * getActiveConnection()
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
Connection::TCP * tcpConnection
Definition indidome.h:608
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.
void setDomeConnection(const uint8_t &value)
setDomeConnection Set Dome connection mode. Child class should call this in the constructor before Do...
INDI::PropertySwitch ShutterParkPolicySP
Definition indidome.h:566
@ SHUTTER_OPEN_ON_UNPARK
Definition indidome.h:570
@ SHUTTER_CLOSE_ON_PARK
Definition indidome.h:569
INDI::PropertyNumber ParkPositionNP
Definition indidome.h:550
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
uint32_t GetDomeCapability() const
GetDomeCapability returns the capability of the dome.
Definition indidome.h:204
@ SHUTTER_ERROR
Definition indidome.h:151
@ SHUTTER_MOVING
Definition indidome.h:149
@ 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
@ CONNECTION_SERIAL
Definition indidome.h:172
@ CONNECTION_TCP
Definition indidome.h:173
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Dome Presets in the configuration file
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
const char * getName() const
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 fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
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_RA
void tty_set_generic_udp_format(int enabled)
Definition indicom.c:364
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
#define MAXRBUF
Definition indidriver.c:52
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_DEBUG(txt)
Definition indilogger.h:75
#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