35static std::unique_ptr<Camelot> camelot(
new Camelot());
56 RotatorSpeedSP[SPEED_FAST].
fill(
"SPEED_FAST",
"Fast",
ISS_OFF);
57 RotatorSpeedSP[SPEED_MEDIUM].
fill(
"SPEED_MEDIUM",
"Medium",
ISS_ON);
58 RotatorSpeedSP[SPEED_SLOW].
fill(
"SPEED_SLOW",
"Slow",
ISS_OFF);
62 RotatorPowerNP[POWER_NORMAL].
fill(
"POWER_NORMAL",
"Normal",
"%.f", 0, 255, 1, 120);
63 RotatorPowerNP[POWER_HOLD].
fill(
"POWER_HOLD",
"Hold",
"%.f", 0, 255, 1, 100);
77 char res[DRIVER_LEN] = {0};
80 if (sendCommand(
"P#", res))
84 double position = std::stod(res) / 10.0;
88 catch (
const std::invalid_argument& ia)
90 LOGF_ERROR(
"Invalid argument for std::stod in updateProperties: %s", ia.what());
93 catch (
const std::out_of_range& oor)
95 LOGF_ERROR(
"Out of range for std::stod in updateProperties: %s", oor.what());
101 if (sendCommand(
"K#", res))
103 if (strstr(res,
"Normal"))
133 return "Camelot Rotator";
141 char res[DRIVER_LEN] = {0};
143 for (
int i = 0; i < 3; i++)
145 if (sendCommand(
"#", res))
147 if (strstr(res,
"OK.ROT!"))
161 char cmd[DRIVER_LEN] = {0};
163 snprintf(
cmd, DRIVER_LEN,
"T%04d",
static_cast<int>(
round(degrees * 10.0)));
164 if (sendCommand(
cmd))
177 return sendCommand(
"L#");
186 return sendCommand(
"D#");
194 char cmd[DRIVER_LEN] = {0};
196 snprintf(
cmd, DRIVER_LEN,
"S%03d",
static_cast<int>(
round(degrees * 10.0)));
197 return sendCommand(
cmd);
209 updateProperty(RotatorSpeedSP, states, names, n, [
this, states, n]
211 char cmd[DRIVER_LEN] = {0};
213 return sendCommand(
cmd);
233 char cmd[DRIVER_LEN] = {0};
234 snprintf(
cmd, DRIVER_LEN,
"*%d",
static_cast<int>(values[POWER_NORMAL]));
235 auto normalOk = sendCommand(
cmd);
236 snprintf(
cmd, DRIVER_LEN,
"+%d",
static_cast<int>(values[POWER_HOLD]));
237 auto holdOk = sendCommand(
cmd);
238 return normalOk && holdOk;
249bool Camelot::queryStatus()
251 char res[DRIVER_LEN] = {0};
254 if (sendCommand(
"Y#", res))
256 if (strstr(res,
"Fast"))
258 else if (strstr(res,
"Medium"))
260 else if (strstr(res,
"Slow"))
265 if (sendCommand(
"R1#", res))
267 RotatorPowerNP[POWER_NORMAL].setValue(std::stoi(res));
270 if (sendCommand(
"R0#", res))
272 RotatorPowerNP[POWER_HOLD].setValue(std::stoi(res));
287 char res[DRIVER_LEN] = {0};
293 if (sendCommand(
"J#", res) && strstr(res,
"M0:OK"))
297 if (sendCommand(
"P#", res))
303 catch (
const std::invalid_argument& ia)
305 LOGF_ERROR(
"Invalid argument for std::stod in TimerHit: %s", ia.what());
307 catch (
const std::out_of_range& oor)
309 LOGF_ERROR(
"Out of range for std::stod in TimerHit: %s", oor.what());
327 RotatorSpeedSP.
save(fp);
328 RotatorPowerNP.
save(fp);
336bool Camelot::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
338 int nbytes_written = 0, nbytes_read = 0, rc = -1;
343 tcflush(
PortFD, TCIOFLUSH);
347 char hex_cmd[DRIVER_LEN * 3] = {0};
348 hexDump(hex_cmd,
cmd, cmd_len);
356 char formatted_command[DRIVER_LEN] = {0};
357 snprintf(formatted_command, DRIVER_LEN,
"%s",
cmd);
365 LOGF_ERROR(
"Serial write error: %s.", errstr);
373 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
396 LOGF_ERROR(
"%s Serial read error after 3 retries: %s.",
cmd, errstr);
402 char hex_res[DRIVER_LEN * 3] = {0};
403 hexDump(hex_res, res, res_len);
409 res[nbytes_read - 1] = 0;
419void Camelot::hexDump(
char * buf,
const char * data, uint32_t size)
421 for (uint32_t i = 0; i < size; i++)
422 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
425 buf[3 * size - 1] =
'\0';
bool SyncRotator(double degrees) override
SyncRotator Set current angle as the supplied angle without moving the rotator.
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
bool Handshake() override
perform handshake with device to check communication
const char * getDefaultName() override
bool saveConfigItems(FILE *fp) override
Save configuration items.
bool AbortRotator() override
AbortRotator Abort all motion.
bool ReverseRotator(bool enabled) override
ReverseRotator Reverse the direction of the rotator. CW is usually the normal direction,...
bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
IPState MoveRotator(double degrees) override
MoveRotator Go to specific angle.
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperty(PropertyType &property, ValueType *values, char *names[], int n, std::function< bool()> updater, bool saveConfig=false)
Generic helper function to update an INDI property based on an external operation.
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 setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
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)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
INDI::PropertySwitch ReverseRotatorSP
INDI::PropertyNumber GotoRotatorNP
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the reverse direction property in the configuration file
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device 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
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.
int IUFindOnStateIndex(ISState *states, int n)
Returns the index of first ON switch it finds in the ISState array.
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)
double round(double value, int decimal_places)