33static std::unique_ptr<RTIDome> rtidome(
new RTIDome());
61 FirmwareTP[FIRMWARE_ROTATION].
fill(
"FIRMWARE_ROTATION",
"Rotation",
"N/A");
62 FirmwareTP[FIRMWARE_SHUTTER].
fill(
"FIRMWARE_SHUTTER",
"Shutter",
"N/A");
66 StatusTP[STATUS_DOME].
fill(
"STATUS_DOME",
"Dome",
"N/A");
67 StatusTP[STATUS_SHUTTER].
fill(
"STATUS_SHUTTER",
"Shutter",
"N/A");
71 SettingsNP[SETTINGS_STEPS_PER_ROTATION].
fill(
"SETTINGS_STEPS_PER_ROTATION",
"Steps/Rotation",
"%.f",
73 SettingsNP[SETTINGS_STEP_RATE].
fill(
"SETTINGS_STEP_RATE",
"Step Rate (steps/s)",
"%.f",
75 SettingsNP[SETTINGS_ACCELERATION].
fill(
"SETTINGS_ACCELERATION",
"Acceleration",
"%.f",
80 HomePositionNP[0].
fill(
"HOME_POSITION",
"Az (deg)",
"%.2f", 0, 360, 1, 0);
84 HomeSP[HOME_FIND].
fill(
"HOME_FIND",
"Find",
ISS_OFF);
88 RainActionSP[RAIN_DO_NOTHING].
fill(
"RAIN_DO_NOTHING",
"Do Nothing",
ISS_ON);
89 RainActionSP[RAIN_GOTO_HOME].
fill(
"RAIN_GOTO_HOME",
"Go Home",
ISS_OFF);
90 RainActionSP[RAIN_GOTO_PARK].
fill(
"RAIN_GOTO_PARK",
"Go Park",
ISS_OFF);
94 ReversedSP[REVERSED_NORMAL].
fill(
"REVERSED_NORMAL",
"Normal",
ISS_ON);
95 ReversedSP[REVERSED_REVERSED].
fill(
"REVERSED_REVERSED",
"Reversed",
ISS_OFF);
99 ShutterVoltsNP[SHUTTER_VOLTAGE_CURRENT].
fill(
"SHUTTER_VOLTAGE_CURRENT",
"Current (V)",
"%.2f", 0, 20, 0, 0);
100 ShutterVoltsNP[SHUTTER_VOLTAGE_CUTOFF].
fill(
"SHUTTER_VOLTAGE_CUTOFF",
"Cutoff (V)",
"%.2f", 0, 20, 0, 0);
122bool RTIDome::setupInitialParameters()
136 if (getFirmwareVersion())
137 FirmwareTP[FIRMWARE_ROTATION].setText(FirmwareTP[FIRMWARE_ROTATION].
getText());
144 if (getDomeAzimuth(az))
151 uint32_t steps = 0, rate = 0, accel = 0;
152 bool settingsOk =
true;
153 if (getStepsPerRotation(steps))
154 SettingsNP[SETTINGS_STEPS_PER_ROTATION].setValue(steps);
157 if (getStepRate(rate))
158 SettingsNP[SETTINGS_STEP_RATE].setValue(rate);
161 if (getAcceleration(accel))
162 SettingsNP[SETTINGS_ACCELERATION].setValue(accel);
171 if (getHomePosition(homeAz))
173 HomePositionNP[0].setValue(homeAz);
176 HomePositionNP.
apply();
180 if (getMotorReversed(rev))
183 ReversedSP[rev ? REVERSED_REVERSED : REVERSED_NORMAL].
setState(
ISS_ON);
190 if (getRainAction(action))
192 RainActionSP.
reset();
193 if (action >= 0 && action <= 2)
196 RainActionSP.
apply();
204 getShutterPresent(m_bShutterPresent);
205 if (m_bShutterPresent)
207 LOG_INFO(
"Shutter controller detected.");
209 getShutterFirmwareVersion();
212 int shutterStatus = 0;
213 if (queryShutterState(shutterStatus))
217 switch (shutterStatus)
237 double voltage = 0, cutoff = 0;
238 if (getShutterVoltage(voltage, cutoff))
240 ShutterVoltsNP[SHUTTER_VOLTAGE_CURRENT].setValue(voltage);
241 ShutterVoltsNP[SHUTTER_VOLTAGE_CUTOFF].setValue(cutoff);
243 ShutterVoltsNP.
apply();
248 LOG_INFO(
"No shutter controller detected. Shutter commands will be skipped.");
259 return getFirmwareVersion();
279 setupInitialParameters();
317 HomeSP.
update(states, names, n);
318 if (HomeSP[HOME_FIND].getState() ==
ISS_ON)
323 LOG_INFO(
"Dome finding home position...");
329 LOG_ERROR(
"Failed to start home search.");
341 RainActionSP.
update(states, names, n);
343 if (setRainAction(action))
353 RainActionSP.
apply();
362 ReversedSP.
update(states, names, n);
364 if (setMotorReversed(rev))
367 LOGF_INFO(
"Motor direction set to: %s", rev ?
"Reversed" :
"Normal");
372 LOG_ERROR(
"Failed to set motor direction.");
395 for (
int i = 0; i < n; i++)
397 if (SettingsNP[SETTINGS_STEPS_PER_ROTATION].isNameMatch(names[i]))
399 if (setStepsPerRotation(
static_cast<uint32_t
>(values[i])))
400 SettingsNP[SETTINGS_STEPS_PER_ROTATION].setValue(values[i]);
404 LOG_ERROR(
"Failed to set steps per rotation.");
407 else if (SettingsNP[SETTINGS_STEP_RATE].isNameMatch(names[i]))
409 if (setStepRate(
static_cast<uint32_t
>(values[i])))
410 SettingsNP[SETTINGS_STEP_RATE].setValue(values[i]);
417 else if (SettingsNP[SETTINGS_ACCELERATION].isNameMatch(names[i]))
419 if (setAcceleration(
static_cast<uint32_t
>(values[i])))
420 SettingsNP[SETTINGS_ACCELERATION].setValue(values[i]);
424 LOG_ERROR(
"Failed to set acceleration.");
438 if (setHomePosition(values[0]))
440 HomePositionNP[0].setValue(values[0]);
442 LOGF_INFO(
"Home position set to %.2f degrees.", values[0]);
447 LOG_ERROR(
"Failed to set home position.");
449 HomePositionNP.
apply();
459 double cutoff = values[SHUTTER_VOLTAGE_CUTOFF];
460 char cmd[DRIVER_LEN] = {0};
461 snprintf(
cmd, DRIVER_LEN,
"K%d",
static_cast<int>(cutoff * 100));
462 char res[DRIVER_LEN] = {0};
463 if (sendCommand(
cmd, res))
466 double voltage = 0, newCutoff = 0;
467 if (getShutterVoltage(voltage, newCutoff))
469 ShutterVoltsNP[SHUTTER_VOLTAGE_CURRENT].setValue(voltage);
470 ShutterVoltsNP[SHUTTER_VOLTAGE_CUTOFF].setValue(newCutoff);
477 LOG_ERROR(
"Failed to set shutter voltage cutoff.");
479 ShutterVoltsNP.
apply();
497 if (getDomeAzimuth(az))
499 if (std::abs(az -
DomeAbsPosNP[0].getValue()) > DOME_AZ_THRESHOLD)
508 if (getSlewingStatus(slewStatus))
510 const char *slewText = (slewStatus == 1) ?
"Slewing CW" : (slewStatus == -1) ?
"Slewing CCW" :
"Idle";
512 if (strcmp(StatusTP[STATUS_DOME].
getText(), slewText) != 0)
514 StatusTP[STATUS_DOME].setText(slewText);
536 if (getHomedStatus(homedStatus) && homedStatus >= 1)
541 LOG_INFO(
"Dome found home position.");
550 ++m_nShutterPollCounter;
551 if (m_nShutterPollCounter >= 10)
553 m_nShutterPollCounter = 0;
554 bool wasPresent = m_bShutterPresent;
556 getShutterPresent(m_bShutterPresent);
557 if (m_bShutterPresent && !wasPresent)
558 LOG_INFO(
"Shutter controller detected.");
559 else if (!m_bShutterPresent && wasPresent)
560 LOG_WARN(
"Shutter controller lost.");
566 if (m_bShutterPresent)
568 int shutterStatus = 0;
569 if (queryShutterState(shutterStatus))
575 const char *shutterText =
nullptr;
578 switch (shutterStatus)
581 shutterText =
"Open";
585 shutterText =
"Closed";
591 shutterText =
"Opening";
597 shutterText =
"Closing";
601 shutterText =
"Bottom Open";
605 shutterText =
"Bottom Closed";
609 shutterText =
"Error";
613 shutterText =
"Unknown";
618 if (strcmp(StatusTP[STATUS_SHUTTER].
getText(), shutterText) != 0)
620 StatusTP[STATUS_SHUTTER].setText(shutterText);
663 return syncAzimuth(az);
679 double jogDeg = (dir ==
DOME_CW) ? 5.0 : -5.0;
709 if (!m_bShutterPresent)
711 LOG_ERROR(
"Cannot control shutter: shutter controller not detected.");
773bool RTIDome::getFirmwareVersion()
775 char res[DRIVER_LEN] = {0};
776 if (!sendCommand(
"v", res))
780 if (res[0] ==
'v' || res[0] ==
'V')
782 FirmwareTP[FIRMWARE_ROTATION].setText(res + 1);
791bool RTIDome::getShutterFirmwareVersion()
793 char res[DRIVER_LEN] = {0};
794 if (!sendCommand(
"V", res))
798 if (res[0] ==
'v' || res[0] ==
'V')
800 FirmwareTP[FIRMWARE_SHUTTER].setText(res + 1);
809bool RTIDome::getDomeAzimuth(
double &az)
811 char res[DRIVER_LEN] = {0};
812 if (!sendCommand(
"g", res))
819 az = std::atof(res + 1);
826bool RTIDome::getSlewingStatus(
int &status)
828 char res[DRIVER_LEN] = {0};
829 if (!sendCommand(
"m", res))
836 status = std::atoi(res + 1);
843bool RTIDome::getHomedStatus(
int &status)
845 char res[DRIVER_LEN] = {0};
846 if (!sendCommand(
"z", res))
853 status = std::atoi(res + 1);
860bool RTIDome::queryShutterState(
int &status)
862 char res[DRIVER_LEN] = {0};
863 if (!sendCommand(
"M", res))
870 status = std::atoi(res + 1);
877bool RTIDome::getStepsPerRotation(uint32_t &steps)
879 char res[DRIVER_LEN] = {0};
880 if (!sendCommand(
"t", res))
887 steps =
static_cast<uint32_t
>(std::stoul(res + 1));
894bool RTIDome::getStepRate(uint32_t &rate)
896 char res[DRIVER_LEN] = {0};
897 if (!sendCommand(
"r", res))
904 rate =
static_cast<uint32_t
>(std::stoul(res + 1));
911bool RTIDome::getAcceleration(uint32_t &accel)
913 char res[DRIVER_LEN] = {0};
914 if (!sendCommand(
"e", res))
921 accel =
static_cast<uint32_t
>(std::stoul(res + 1));
928bool RTIDome::getHomePosition(
double &az)
930 char res[DRIVER_LEN] = {0};
931 if (!sendCommand(
"i", res))
938 az = std::atof(res + 1);
945bool RTIDome::getParkPosition(
double &az)
947 char res[DRIVER_LEN] = {0};
948 if (!sendCommand(
"l", res))
955 az = std::atof(res + 1);
962bool RTIDome::getMotorReversed(
bool &reversed)
964 char res[DRIVER_LEN] = {0};
965 if (!sendCommand(
"y", res))
972 reversed = (res[1] ==
'1');
979bool RTIDome::getRainAction(
int &action)
981 char res[DRIVER_LEN] = {0};
982 if (!sendCommand(
"n", res))
989 action = std::atoi(res + 1);
996bool RTIDome::getRainStatus(
bool &raining)
998 char res[DRIVER_LEN] = {0};
999 if (!sendCommand(
"F", res))
1006 raining = (res[1] ==
'1');
1013bool RTIDome::getShutterVoltage(
double &voltage,
double &cutoff)
1015 char res[DRIVER_LEN] = {0};
1016 if (!sendCommand(
"K", res))
1023 int raw_v = 0, raw_c = 0;
1024 if (sscanf(res + 1,
"%d,%d", &raw_v, &raw_c) != 2)
1027 voltage = raw_v / 100.0;
1028 cutoff = raw_c / 100.0;
1035bool RTIDome::gotoAzimuth(
double az)
1037 char cmd[DRIVER_LEN] = {0};
1038 snprintf(
cmd, DRIVER_LEN,
"g%.2f", az);
1039 char res[DRIVER_LEN] = {0};
1040 if (!sendCommand(
cmd, res))
1042 return (res[0] ==
'g');
1048bool RTIDome::syncAzimuth(
double az)
1050 char cmd[DRIVER_LEN] = {0};
1051 snprintf(
cmd, DRIVER_LEN,
"s%.2f", az);
1052 char res[DRIVER_LEN] = {0};
1053 if (!sendCommand(
cmd, res))
1055 return (res[0] ==
's');
1061bool RTIDome::stopDome()
1063 char res[DRIVER_LEN] = {0};
1064 if (!sendCommand(
"a", res))
1066 return (res[0] ==
'a');
1072bool RTIDome::findHome()
1074 char res[DRIVER_LEN] = {0};
1075 if (!sendCommand(
"h", res))
1077 return (res[0] ==
'h');
1083bool RTIDome::setHomePosition(
double az)
1085 char cmd[DRIVER_LEN] = {0};
1086 snprintf(
cmd, DRIVER_LEN,
"i%.2f", az);
1087 char res[DRIVER_LEN] = {0};
1088 if (!sendCommand(
cmd, res))
1090 return (res[0] ==
'i');
1096bool RTIDome::setParkPosition(
double az)
1098 char cmd[DRIVER_LEN] = {0};
1099 snprintf(
cmd, DRIVER_LEN,
"l%.2f", az);
1100 char res[DRIVER_LEN] = {0};
1101 if (!sendCommand(
cmd, res))
1103 return (res[0] ==
'l');
1109bool RTIDome::setStepsPerRotation(uint32_t steps)
1111 char cmd[DRIVER_LEN] = {0};
1112 snprintf(
cmd, DRIVER_LEN,
"t%u", steps);
1113 char res[DRIVER_LEN] = {0};
1114 if (!sendCommand(
cmd, res))
1116 return (res[0] ==
't');
1122bool RTIDome::setStepRate(uint32_t rate)
1124 char cmd[DRIVER_LEN] = {0};
1125 snprintf(
cmd, DRIVER_LEN,
"r%u", rate);
1126 char res[DRIVER_LEN] = {0};
1127 if (!sendCommand(
cmd, res))
1129 return (res[0] ==
'r');
1135bool RTIDome::setAcceleration(uint32_t accel)
1137 char cmd[DRIVER_LEN] = {0};
1138 snprintf(
cmd, DRIVER_LEN,
"e%u", accel);
1139 char res[DRIVER_LEN] = {0};
1140 if (!sendCommand(
cmd, res))
1142 return (res[0] ==
'e');
1148bool RTIDome::setMotorReversed(
bool reversed)
1150 char cmd[DRIVER_LEN] = {0};
1151 snprintf(
cmd, DRIVER_LEN,
"y%d", reversed ? 1 : 0);
1152 char res[DRIVER_LEN] = {0};
1153 if (!sendCommand(
cmd, res))
1155 return (res[0] ==
'y');
1161bool RTIDome::setRainAction(
int action)
1163 char cmd[DRIVER_LEN] = {0};
1164 snprintf(
cmd, DRIVER_LEN,
"n%d", action);
1165 char res[DRIVER_LEN] = {0};
1166 if (!sendCommand(
cmd, res))
1168 return (res[0] ==
'n');
1174bool RTIDome::openShutter()
1176 char res[DRIVER_LEN] = {0};
1177 if (!sendCommand(
"O", res))
1182 if (strlen(res) > 1 && res[1] ==
'L')
1184 LOG_WARN(
"Shutter refused to open: low voltage.");
1187 if (strlen(res) > 1 && res[1] ==
'R')
1189 LOG_WARN(
"Shutter refused to open: rain detected.");
1198bool RTIDome::closeShutter()
1200 char res[DRIVER_LEN] = {0};
1201 if (!sendCommand(
"C", res))
1203 return (res[0] ==
'C');
1215bool RTIDome::sendShutterHello()
1217 char res[DRIVER_LEN] = {0};
1218 return sendCommand(
"H", res);
1226bool RTIDome::getShutterPresent(
bool &present)
1228 char res[DRIVER_LEN] = {0};
1229 if (!sendCommand(
"o", res))
1242 present = (res[1] ==
'1');
1249bool RTIDome::sendCommand(
const char *
cmd,
char *res)
1251 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1253 tcflush(
PortFD, TCIOFLUSH);
1256 char formatted_command[DRIVER_LEN] = {0};
1257 snprintf(formatted_command, DRIVER_LEN,
"%s#",
cmd);
1266 LOGF_ERROR(
"Serial write error: %s.", errstr);
1279 LOGF_ERROR(
"Serial read error: %s.", errstr);
1284 if (nbytes_read > 0 && res[nbytes_read - 1] == DRIVER_STOP_CHAR)
1285 res[nbytes_read - 1] =
'\0';
1289 tcflush(
PortFD, TCIOFLUSH);
1297void RTIDome::hexDump(
char *buf,
const char *data,
int size)
1299 for (
int i = 0; i < size; i++)
1300 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
1303 buf[3 * size - 1] =
'\0';
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 setDefaultPort(uint32_t addressPort)
INDI::PropertyText getText(const char *name) const
void setActiveConnection(Connection::Interface *existingConnection)
setActiveConnection Switch the active connection to the passed connection plugin
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.
Connection::TCP * tcpConnection
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...
ShutterState m_ShutterState
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.
INDI::PropertySwitch ParkSP
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.
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
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)
INDI::WidgetViewSwitch * findOnSwitch() const
int findOnSwitchIndex() const
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 IPState ControlShutter(ShutterOperation operation) override
Open or Close shutter.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
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 IPState Park() override
Goto Park Position. The park position is an absolute azimuth value.
virtual IPState MoveRel(double azDiff) override
Move the Dome to an relative position.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual const char * getDefaultName() override
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool Abort() override
Abort all dome motion.
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
virtual bool Sync(double az) override
Sync sets the dome current azimuth as the supplied azimuth position.
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.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
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.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)