34static std::unique_ptr<RigelDome> rigelDome(
new RigelDome());
40#define SIM_SHUTTER_TIMER 5.0
41#define SIM_FLAP_TIMER 5.0
42#define SIM_DOME_HI_SPEED 5.0
43#define SIM_DOME_LO_SPEED 0.5
60 OperationSP[OPERATION_FIND_HOME].
fill(
"OPERATION_FIND_HOME",
"Find Home",
ISS_OFF);
61 OperationSP[OPERATION_CALIBRATE].
fill(
"OPERATION_CALIBRATE",
"Calibrate",
ISS_OFF);
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");
70 HomePositionNP[
AXIS_AZ].
fill(
"HOME_AZ",
"AZ D:M:S",
"%10.6m", 0.0, 360.0, 0.0, 0);
79 stuckAngleCounter = 0;
87bool RigelDome::getStartupValues()
99 if (readShutterStatus())
102 if (readHomePosition())
103 HomePositionNP.
apply();
125 char res[DRIVER_LEN] = {0};
126 sendCommand(
"PULSAR", res);
128 bool rc = readShutterStatus();
181 if (OperationSP[OPERATION_FIND_HOME].isNameMatch(requestedOperation))
186 OperationSP[OPERATION_FIND_HOME].s =
ISS_ON;
188 LOG_INFO(
"Dome is moving to home position...");
196 else if (OperationSP[OPERATION_CALIBRATE].isNameMatch(requestedOperation))
201 OperationSP[OPERATION_CALIBRATE].s =
ISS_ON;
229 HomePositionNP.
update(values, names, n);
231 auto homeAz = HomePositionNP[
AXIS_AZ].getValue();
233 LOGF_INFO(
"Setting home position to %3.1f", homeAz);
234 HomePositionNP.
apply();
263 if (std::abs(currentAngle - previousAngle) < ANGLE_TOLERANCE && isMoving)
267 if (stuckAngleCounter >= STUCK_THRESHOLD)
269 stuckAngleCounter = 0;
270 char res[DRIVER_LEN] = {0};
272 if (sendCommand(
"STOP", res))
274 double diff = std::abs(targetAz - currentAngle);
279 LOGF_INFO(
"Motor stopped after %d cycles with no movement. Current: %.3f°, Target: %.3f°, Difference: %.3f°",
280 STUCK_THRESHOLD, currentAngle, targetAz, diff);
290 stuckAngleCounter = 0;
293 previousAngle = currentAngle;
303 LOG_INFO(
"Dome completed homing...");
309 else if (isCalibrating)
311 LOG_INFO(
"Dome completed calibration...");
338 ShutterState newShutterState = parseShutterState(m_rawShutterState);
344 if (readBatteryLevels())
356 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
359 snprintf(
cmd, DRIVER_LEN,
"GO %3.1f", az);
360 if (sendCommand(
cmd, res) ==
false)
364 stuckAngleCounter = 0;
384 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
387 snprintf(
cmd, DRIVER_LEN,
"ANGLE K %3.1f", az);
388 if (sendCommand(
cmd, res) ==
false)
391 return (res[0] ==
'A');
410 if (setParkAz(targetAz))
413 stuckAngleCounter = 0;
415 char res[DRIVER_LEN] = {0};
416 if (sendCommand(
"GO P", res) ==
false)
427bool RigelDome::home()
430 stuckAngleCounter = 0;
431 targetAz = HomePositionNP[0].getValue();
433 char res[DRIVER_LEN] = {0};
434 if (sendCommand(
"GO H", res) ==
false)
437 return (res[0] ==
'A');
443bool RigelDome::calibrate()
446 stuckAngleCounter = 0;
448 char res[DRIVER_LEN] = {0};
449 if (sendCommand(
"CALIBRATE", res) ==
false)
452 return (res[0] ==
'A');
458bool RigelDome::setHome(
double az)
460 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
463 snprintf(
cmd, DRIVER_LEN,
"HOME %3.1f", az);
464 if (sendCommand(
cmd, res) ==
false)
467 return (res[0] ==
'A');
493 char res[DRIVER_LEN] = {0};
497 m_TargetShutter = operation;
498 sendCommand(
"OPEN", res);
502 m_TargetShutter = operation;
503 sendCommand(
"CLOSE", res);
514 if (sendCommand(
"STOP"))
517 stuckAngleCounter = 0;
521 LOGF_INFO(
"%s is aborted.", OperationSP[OPERATION_CALIBRATE].getState() ==
ISS_ON ?
"Calibration" :
"Finding home");
530 LOG_WARN(
"Shutter motion aborted!");
565bool RigelDome::setShutterConnected(
bool enabled)
567 char cmd[DRIVER_LEN] = {0};
568 snprintf(
cmd, DRIVER_LEN,
"BBOND %d", enabled ? 1 : 0);
569 return sendCommand(
cmd);
575bool RigelDome::isShutterConnected()
577 char res[DRIVER_LEN] = {0};
578 if (sendCommand(
"BBOND", res) ==
false)
580 bool rc = (std::stoi(res) != 0);
581 LOGF_DEBUG(
"Shutter is %s.", (rc ?
"connected" :
"disconnected"));
588bool RigelDome::readStepsPerRevolution()
590 char res[DRIVER_LEN] = {0};
591 if (sendCommand(
"ENCREV", res) ==
false)
594 InfoTP[INFO_TICKS].setText(res);
601bool RigelDome::readBatteryLevels()
603 char res[DRIVER_LEN] = {0};
604 if (sendCommand(
"BAT", res) ==
false)
610 if (sscanf(res,
"%d %lf", &percent, &volts) != 2)
613 char levels[DRIVER_LEN] = {0};
614 snprintf(levels, DRIVER_LEN,
"%.2fv (%d%%)", volts / 1000.0, percent);
615 InfoTP[INFO_BATTERY].setText(levels);
622bool RigelDome::readPosition()
624 char res[DRIVER_LEN] = {0};
625 if (sendCommand(
"ANGLE", res) ==
false)
632bool RigelDome::readHomePosition()
634 char res[DRIVER_LEN] = {0};
636 if (sendCommand(
"HOME", res) ==
false)
639 HomePositionNP[0].setValue(std::stod(res));
646bool RigelDome::setParkAz(
double az)
648 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
650 snprintf(
cmd, DRIVER_LEN,
"PARK %3.1f", az);
651 if (sendCommand(
cmd, res) ==
false)
654 return res[0] ==
'A';
660bool RigelDome::readState()
662 char res[DRIVER_LEN] = {0};
663 if (sendCommand(
"V", res) ==
false)
666 std::vector<std::string> fields = split(res,
"\t");
667 if (fields.size() < 13)
705bool RigelDome::readShutterStatus()
707 char res[DRIVER_LEN] = {0};
708 if (sendCommand(
"SHUTTER", res) ==
false)
718bool RigelDome::readFirmware()
720 char res[DRIVER_LEN] = {0};
722 if (sendCommand(
"VER", res) ==
false)
725 InfoTP[INFO_FIRMWARE].setText(res);
732bool RigelDome::readModel()
734 char res[DRIVER_LEN] = {0};
736 if (sendCommand(
"PULSAR", res) ==
false)
739 InfoTP[INFO_MODEL].setText(res);
746bool RigelDome::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
748 int nbytes_written = 0, nbytes_read = 0, rc = -1;
750 tcflush(
PortFD, TCIOFLUSH);
754 char hex_cmd[DRIVER_LEN * 3] = {0};
755 hexDump(hex_cmd,
cmd, cmd_len);
763 char formatted_command[DRIVER_LEN] = {0};
764 snprintf(formatted_command, DRIVER_LEN,
"%s\r",
cmd);
772 LOGF_ERROR(
"Serial write error: %s.", errstr);
780 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
794 char hex_res[DRIVER_LEN * 3] = {0};
795 hexDump(hex_res, res, res_len);
801 res[nbytes_read - 1] = 0;
805 tcflush(
PortFD, TCIOFLUSH);
813void RigelDome::hexDump(
char * buf,
const char * data,
int size)
815 for (
int i = 0; i < size; i++)
816 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
819 buf[3 * size - 1] =
'\0';
825std::vector<std::string> RigelDome::split(
const std::string &input,
const std::string ®ex)
828 std::regex re(regex);
829 std::sregex_token_iterator
830 first{input.begin(), input.end(), re, -1},
832 return {first, last};
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
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
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.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
uint32_t GetDomeCapability() const
GetDomeCapability returns the capability of the dome.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
INDI::PropertyNumber DomeAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
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
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
ShutterState getShutterState() const
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
DomeState getDomeState() const
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.
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.
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
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
Implementations for common driver routines.
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)