43static std::unique_ptr<PegasusFalcon> falcon(
new PegasusFalcon());
48 lastStatusData.reserve(7);
66 ReloadFirmwareSP[0].
fill(
"RELOAD",
"Reload",
ISS_OFF);
72 DerotateNP[0].
fill(
"INTERVAL",
"Interval (ms)",
"%.f", 0, 10000, 1000, 0);
77 FirmwareTP[0].
fill(
"VERSION",
"Version",
"NA");
109 return "Pegasus Falcon";
115bool PegasusFalcon::Handshake()
117 return getFirmware();
130 const uint32_t ms =
static_cast<uint32_t
>(values[0]);
131 if (setDerotation(ms))
133 DerotateNP[0].setValue(values[0]);
135 LOGF_INFO(
"De-rotation is enabled and set to 1 step per %u milliseconds.", ms);
137 LOG_INFO(
"De-rotaiton is disabled.");
147 else if (!strcmp(name,
"ABS_ROTATOR_ANGLE"))
149 if (std::abs(values[0] -
GotoRotatorNP[0].getValue()) <= 0.01)
157 return Rotator::ISNewNumber(dev, name, values, names, n);
171 ReloadFirmwareSP.
apply();
177 return Rotator::ISNewSwitch(dev, name, states, names, n);
185 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
186 snprintf(
cmd, DRIVER_LEN,
"MD:%.2f", angle);
187 if (sendCommand(
cmd, res))
201 char res[DRIVER_LEN] = {0};
202 if (sendCommand(
"FH", res))
204 return (!strcmp(res,
"FH:1"));
215 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
216 snprintf(
cmd, DRIVER_LEN,
"FN:%d", enabled ? 1 : 0);
217 if (sendCommand(
cmd, res))
219 return (!strncmp(res,
cmd, 4));
230 char cmd[DRIVER_LEN] = {0};
231 snprintf(
cmd, DRIVER_LEN,
"SD:%.2f", angle);
232 return sendCommand(
cmd,
nullptr);
238bool PegasusFalcon::reloadFirmware()
240 return sendCommand(
"FF");
246bool PegasusFalcon::setDerotation(uint32_t ms)
248 char cmd[DRIVER_LEN] = {0};
249 snprintf(
cmd, DRIVER_LEN,
"DR:%d", ms);
250 return sendCommand(
cmd,
nullptr);
277bool PegasusFalcon::getFirmware()
279 char res[DRIVER_LEN] = {0};
280 if (sendCommand(
"FV", res))
282 FirmwareTP[0].setText(res + 3);
292bool PegasusFalcon::getStatusData()
294 char res[DRIVER_LEN] = {0};
295 if (sendCommand(
"FA", res))
297 std::vector<std::string> result = split(res,
":");
298 if (result.size() != 7)
300 LOG_WARN(
"Received wrong number of detailed sensor data. Retrying...");
304 if (result == lastStatusData)
308 const double position = std::stod(result[2]);
323 const bool derotation = std::stoi(result[5]) == 1;
324 const bool wasDerotated = DerotateNP[0].getValue() > 0;
326 if (derotation != wasDerotated)
332 const bool reversed = std::stoi(result[6]) == 1;
334 if (reversed != wasReversed)
341 lastStatusData = result;
351bool PegasusFalcon::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
353 int nbytes_written = 0, nbytes_read = 0, rc = -1;
355 tcflush(
PortFD, TCIOFLUSH);
359 char hex_cmd[DRIVER_LEN * 3] = {0};
360 hexDump(hex_cmd,
cmd, cmd_len);
368 char formatted_command[DRIVER_LEN] = {0};
369 snprintf(formatted_command, DRIVER_LEN,
"%s\n",
cmd);
377 LOGF_ERROR(
"Serial write error: %s.", errstr);
385 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
399 char hex_res[DRIVER_LEN * 3] = {0};
400 hexDump(hex_res, res, res_len);
406 res[nbytes_read - 1] = 0;
410 tcflush(
PortFD, TCIOFLUSH);
418void PegasusFalcon::hexDump(
char * buf,
const char * data, uint32_t size)
420 for (uint32_t i = 0; i < size; i++)
421 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
424 buf[3 * size - 1] =
'\0';
430std::vector<std::string> PegasusFalcon::split(
const std::string &input,
const std::string ®ex)
433 std::regex re(regex);
434 std::sregex_token_iterator
435 first{input.begin(), input.end(), re, -1},
437 return {first, last};
443void PegasusFalcon::cleanupResponse(
char *response)
445 std::string s(response);
446 s.erase(std::remove_if(s.begin(), s.end(),
449 return std::isspace(x);
451 snprintf(response, DRIVER_LEN,
"%s", s.c_str());
void setPortMatchPattern(const std::string &pattern)
setPortMatchPattern Set a regex pattern used to automatically select a serial port from the discovere...
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 fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, 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
Connection::Serial * serialConnection
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
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
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual IPState MoveRotator(double angle) override
move to degrees (Command "MD:nn.nn"; Response "MD:nn.nn")
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 AbortRotator() override
AbortRotator Abort all motion.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ReverseRotator(bool enabled) override
reverse action ("FN:0" disabled, "FN:1" enabled)
virtual bool SyncRotator(double angle) override
SyncRotator Set current angle as the supplied angle without moving the rotator.
const char * getDefaultName() override
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.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)