76 static std::unique_ptr<SestoSenso> sesto(
new SestoSenso());
90 IUFillText(&FirmwareT[0],
"VERSION",
"Version",
"");
95 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
100 IUFillText(&CalibrationMessageT[0],
"CALIBRATION",
"Calibration stage",
"");
137 m_MotionProgressTimer.
callOnTimeout(std::bind(&SestoSenso::checkMotionProgressCallback,
this));
150 if (updateTemperature())
153 IUSaveText(&CalibrationMessageT[0],
"Press START to begin the Calibration");
157 if (getStartupValues())
158 LOG_INFO(
"SestoSenso parameters updated, focuser ready for use.");
160 LOG_WARN(
"Failed to inquire parameters. Check logs.");
178 LOG_INFO(
"SestoSenso is online. Getting focus parameters...");
183 "Error retrieving data from SestoSenso, please ensure SestoSenso controller is powered and the port is correct.");
198 return "Sesto Senso";
201 bool SestoSenso::Ack()
203 char res[SESTO_LEN] = {0};
206 strncpy(res,
"1.0 Simulation", SESTO_LEN);
207 else if (sendCommand(
"#QF!", res) ==
false)
215 bool SestoSenso::updateTemperature()
217 char res[SESTO_LEN] = {0};
218 double temperature = 0;
221 strncpy(res,
"23.45", SESTO_LEN);
222 else if (sendCommand(
"#QT!", res) ==
false)
227 temperature = std::stod(res);
231 LOGF_WARN(
"Failed to process temperature response: %s (%d bytes)", res, strlen(res));
235 if (temperature > 90)
238 TemperatureN[0].value = temperature;
244 bool SestoSenso::updateMaxLimit()
246 char res[SESTO_LEN] = {0};
251 if (sendCommand(
"#QM!", res) ==
false)
256 sscanf(res,
"QM;%d!", &maxLimit);
286 bool SestoSenso::updatePosition()
288 char res[SESTO_LEN] = {0};
290 snprintf(res, SESTO_LEN,
"%d",
static_cast<uint32_t
>(
FocusAbsPosN[0].value));
291 else if (sendCommand(
"#QP!", res) ==
false)
302 LOGF_WARN(
"Failed to process position response: %s (%d bytes)", res, strlen(res));
308 bool SestoSenso::isMotionComplete()
310 char res[SESTO_LEN] = {0};
315 int32_t targPos =
static_cast<int32_t
>(targetPos);
317 if (targPos > nextPos)
319 else if (targPos < nextPos)
322 if (abs(nextPos - targPos) < 250)
324 else if (nextPos < 0)
329 snprintf(res, SESTO_LEN,
"%d", nextPos);
340 res[nbytes_read - 1] = 0;
343 if (!strcmp(res,
"GTok!"))
348 uint32_t newPos = std::stoi(res);
353 LOGF_WARN(
"Failed to process motion response: %s (%d bytes)", res, strlen(res));
368 if (!strcmp(name, CalibrationSP.
name))
370 char res[SESTO_LEN] = {0};
371 int current_switch = 0;
378 CalibrationS[current_switch].s =
ISS_ON;
381 if (current_switch == CALIBRATION_START)
383 if (cStage == Idle || cStage == Complete )
393 if (sendCommand(
"#MF!") ==
false)
396 IUSaveText(&CalibrationMessageT[0],
"Move focuser manually to the middle then press NEXT");
397 IDSetText(&CalibrationMessageTP,
nullptr);
404 LOG_INFO(
"Already started calibration. Proceed to next step.");
405 IUSaveText(&CalibrationMessageT[0],
"Already started. Proceed to NEXT.");
406 IDSetText(&CalibrationMessageTP,
nullptr);
409 else if (current_switch == CALIBRATION_NEXT)
411 if (cStage == GoToMiddle)
414 IUSaveText(&CalibrationMessageT[0],
"Move In/Move Out/Stop to MIN position then press NEXT");
415 IDSetText(&CalibrationMessageTP,
nullptr);
418 else if (cStage == GoMinimum)
421 if (sendCommand(
"#Sm;0!") ==
false)
424 IUSaveText(&CalibrationMessageT[0],
"Move In/Move Out/Stop to MAX position then press NEXT");
425 IDSetText(&CalibrationMessageTP,
nullptr);
428 else if (cStage == GoMaximum)
433 if (sendCommand(
"#SM!", res) ==
false)
435 if (sendCommand(
"#PS!") ==
false)
442 sscanf(res,
"SM;%d!", &maxLimit);
443 LOGF_INFO(
"MAX setting is %d", maxLimit);
463 IUSaveText(&CalibrationMessageT[0],
"Calibration Completed.");
464 IDSetText(&CalibrationMessageTP,
nullptr);
472 CalibrationS[current_switch].s =
ISS_OFF;
477 IUSaveText(&CalibrationMessageT[0],
"Calibration not in process");
478 IDSetText(&CalibrationMessageTP,
nullptr);
484 else if (!strcmp(name, FastMoveSP.
name))
489 switch (current_switch)
492 if (sendCommand(
"#FI!") ==
false)
498 if (sendCommand(
"#FO!") ==
false)
504 if (sendCommand(
"#MA!") ==
false)
524 targetPos = targetTicks;
526 char cmd[SESTO_LEN] = {0};
527 snprintf(
cmd, 16,
"#GT%u!", targetTicks);
530 if (sendCommand(
cmd) ==
false)
534 m_MotionProgressTimer.
start(10);
541 int relativeTicks = ((dir ==
FOCUS_INWARD) ? -ticks : ticks) * reversed;
542 double newPosition =
FocusAbsPosN[0].value + relativeTicks;
551 m_MotionProgressTimer.
stop();
556 return sendCommand(
"#MA!");
564 void SestoSenso::checkMotionProgressCallback()
566 if (isMotionComplete())
573 LOG_INFO(
"Focuser reached requested position.");
581 m_MotionProgressTimer.
start(250);
592 bool rc = updatePosition();
602 if (m_TemperatureCounter++ == SESTO_TEMPERATURE_FREQ)
604 rc = updateTemperature();
607 if (fabs(lastTemperature - TemperatureN[0].value) >= 0.1)
610 lastTemperature = TemperatureN[0].value;
613 m_TemperatureCounter = 0;
619 bool SestoSenso::getStartupValues()
621 bool rc1 = updatePosition();
625 if (updateMaxLimit() ==
false)
626 LOG_WARN(
"Check you have the latest SestoSenso firmware. Focuser requires calibration.");
631 bool SestoSenso::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
633 int nbytes_written = 0, nbytes_read = 0, rc = -1;
635 tcflush(
PortFD, TCIOFLUSH);
639 char hex_cmd[SESTO_LEN * 3] = {0};
640 hexDump(hex_cmd,
cmd, cmd_len);
654 LOGF_ERROR(
"Serial write error: %s.", errstr);
666 res[nbytes_read - 1] = 0;
679 char hex_res[SESTO_LEN * 3] = {0};
680 hexDump(hex_res, res, res_len);
688 tcflush(
PortFD, TCIOFLUSH);
693 void SestoSenso::hexDump(
char * buf,
const char * data,
int size)
695 for (
int i = 0; i < size; i++)
696 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
699 buf[3 * size - 1] =
'\0';
const char * getDeviceName() const
virtual bool Disconnect()
Disconnect from device.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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.
bool isSimulation() const
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.
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
ISwitchVectorProperty FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INumberVectorProperty FocusMaxPosNP
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 initProperties() override
Initilize properties initial state and value. The child class must implement this function.
void setSingleShot(bool singleShot)
Set whether the timer is a single-shot timer.
void callOnTimeout(const std::function< void()> &callback)
void start()
Starts or restarts the timer with the timeout specified in interval.
void stop()
Stops the timer.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
const char * getDefaultName() override
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool Disconnect() override
Disconnect from device.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
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.
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)