36static std::unique_ptr<DeepSkyDadAF1> deepSkyDadAf1(
new DeepSkyDadAF1());
72 FocusMaxMoveNP[0].
fill(
"MAX_MOVE",
"Steps",
"%7.0f", 0, 9999999, 100, 0);
77 SettleBufferNP[0].
fill(
"SETTLE_BUFFER",
"Period (ms)",
"%5.0f", 0, 99999, 100, 0);
82 IUFillNumber(&IdleCoilsTimeoutN[0],
"IDLE_COILS_TIMEOUT",
"Period (ms)",
"%6.0f", 0, 999999, 1000, 60000);
84 "Idle - coils timeout",
132 LOG_INFO(
"deepSkyDadAf1 parameters updated, focuser ready for use.");
152 LOG_INFO(
"deepSkyDadAf1 is online. Getting focus parameters...");
157 "Error retrieving data from deepSkyDadAf1, please ensure deepSkyDadAf1 controller is powered and the port is correct.");
163 return "Deep Sky Dad AF1";
166bool DeepSkyDadAF1::Ack()
170 char res[DSD_RES] = {0};
171 if (!sendCommand(
"[GPOS]", res))
178 int rc = sscanf(res,
"(%d)", &pos);
189bool DeepSkyDadAF1::readStepMode()
191 char res[DSD_RES] = {0};
193 if (sendCommand(
"[GSTP]", res) ==
false)
196 if (strcmp(res,
"(1)") == 0)
198 else if (strcmp(res,
"(2)") == 0)
200 else if (strcmp(res,
"(4)") == 0)
202 else if (strcmp(res,
"(8)") == 0)
206 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
213bool DeepSkyDadAF1::readPosition()
215 char res[DSD_RES] = {0};
217 if (sendCommand(
"[GPOS]", res) ==
false)
221 int rc = sscanf(res,
"(%d)", &pos);
227 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
234bool DeepSkyDadAF1::readMaxMovement()
236 char res[DSD_RES] = {0};
238 if (sendCommand(
"[GMXM]", res) ==
false)
242 int rc = sscanf(res,
"(%d)", &steps);
245 FocusMaxMoveNP[0].setValue(steps);
250 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
257bool DeepSkyDadAF1::readMaxPosition()
259 char res[DSD_RES] = {0};
261 if (sendCommand(
"[GMXP]", res) ==
false)
265 int rc = sscanf(res,
"(%d)", &steps);
273 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
280bool DeepSkyDadAF1::readSettleBuffer()
282 char res[DSD_RES] = {0};
284 if (sendCommand(
"[GBUF]", res) ==
false)
287 uint32_t settleBuffer = 0;
288 int rc = sscanf(res,
"(%d)", &settleBuffer);
291 SettleBufferNP[0].setValue(settleBuffer);
296 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
303bool DeepSkyDadAF1::readIdleCoilsTimeout()
305 char res[DSD_RES] = {0};
307 if (sendCommand(
"[GIDC]", res) ==
false)
311 int rc = sscanf(res,
"(%d)", &ms);
314 IdleCoilsTimeoutN[0].value = ms;
319 LOGF_ERROR(
"Unknown error: idle coils timeout value (%s)", res);
326bool DeepSkyDadAF1::readCoilsMode()
328 char res[DSD_RES] = {0};
330 if (sendCommand(
"[GCLM]", res) ==
false)
333 if (strcmp(res,
"(0)") == 0)
338 else if (strcmp(res,
"(1)") == 0)
343 else if (strcmp(res,
"(2)") == 0)
350 LOGF_ERROR(
"Unknown error: readCoilsMode value (%s)", res);
357bool DeepSkyDadAF1::readCurrentMove()
359 char res[DSD_RES] = {0};
361 if (sendCommand(
"[GCMV%]", res) ==
false)
364 if (strcmp(res,
"(25%)") == 0)
369 else if (strcmp(res,
"(50%)") == 0)
374 else if (strcmp(res,
"(75%)") == 0)
379 else if (strcmp(res,
"(100%)") == 0)
387 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
394bool DeepSkyDadAF1::readCurrentHold()
396 char res[DSD_RES] = {0};
398 if (sendCommand(
"[GCHD%]", res) ==
false)
401 if (strcmp(res,
"(25%)") == 0)
406 else if (strcmp(res,
"(50%)") == 0)
411 else if (strcmp(res,
"(75%)") == 0)
416 else if (strcmp(res,
"(100%)") == 0)
424 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
431bool DeepSkyDadAF1::isMoving()
433 char res[DSD_RES] = {0};
435 if (sendCommand(
"[GMOV]", res) ==
false)
438 if (strcmp(res,
"(1)") == 0)
440 else if (strcmp(res,
"(0)") == 0)
443 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
449 char cmd[DSD_RES] = {0};
450 snprintf(
cmd, DSD_RES,
"[SPOS%06d]", ticks);
451 return sendCommand(
cmd);
456 char cmd[DSD_RES] = {0};
457 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
458 return sendCommand(
cmd);
463 char cmd[DSD_RES] = {0};
464 char res[DSD_RES] = {0};
465 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
467 if (sendCommand(
cmd, res) ==
false)
470 if(strcmp(res,
"!101)") == 0)
472 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
477 if (sendCommand(
"[SMOV]") ==
false)
492 StepModeSP.
update(states, names, n);
496 if (current_mode == target_mode)
503 char cmd[DSD_RES] = {0};
507 else if(target_mode == 1)
509 else if(target_mode == 2)
511 else if(target_mode == 3)
514 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
515 bool rc = sendCommandSet(
cmd);
535 CoilsModeSP.
update(states, names, n);
539 if (coilsModeCurrent == coilsModeTarget)
545 if(coilsModeTarget == 0)
547 else if(coilsModeTarget == 1)
549 else if(coilsModeTarget == 2)
552 char cmd[DSD_RES] = {0};
553 snprintf(
cmd, DSD_RES,
"[SCLM%d]", coilsModeTarget);
555 bool rc = sendCommandSet(
cmd);
575 CurrentMoveSP.
update(states, names, n);
579 if (current == targetCurrent)
581 CurrentMoveSP.
apply();
585 int targetCurrentValue = 75;
586 switch(targetCurrent)
589 targetCurrentValue = 25;
592 targetCurrentValue = 50;
595 targetCurrentValue = 75;
598 targetCurrentValue = 100;
602 char cmd[DSD_RES] = {0};
603 snprintf(
cmd, DSD_RES,
"[SCMV%d%%]", targetCurrentValue);
605 bool rc = sendCommandSet(
cmd);
608 CurrentMoveSP.
reset();
611 CurrentMoveSP.
apply();
616 CurrentMoveSP.
apply();
625 CurrentHoldSP.
update(states, names, n);
629 if (current == targetCurrent)
631 CurrentHoldSP.
apply();
635 int targetCurrentValue = 75;
636 switch(targetCurrent)
639 targetCurrentValue = 25;
642 targetCurrentValue = 50;
645 targetCurrentValue = 75;
648 targetCurrentValue = 100;
652 char cmd[DSD_RES] = {0};
653 snprintf(
cmd, DSD_RES,
"[SCHD%d%%]", targetCurrentValue);
655 bool rc = sendCommandSet(
cmd);
658 CurrentHoldSP.
reset();
661 CurrentHoldSP.
apply();
666 CurrentHoldSP.
apply();
681 SettleBufferNP.
update(values, names, n);
682 char cmd[DSD_RES] = {0};
683 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferNP[0].getValue()));
684 bool rc = sendCommandSet(
cmd);
692 SettleBufferNP.
apply();
697 if (strcmp(name, IdleCoilsTimeoutNP.
name) == 0)
700 char cmd[DSD_RES] = {0};
701 snprintf(
cmd, DSD_RES,
"[SIDC%06d]",
static_cast<int>(IdleCoilsTimeoutN[0].value));
702 bool rc = sendCommandSet(
cmd);
718 FocusMaxMoveNP.
update(values, names, n);
719 char cmd[DSD_RES] = {0};
720 snprintf(
cmd, DSD_RES,
"[SMXM%d]",
static_cast<int>(FocusMaxMoveNP[0].getValue()));
721 bool rc = sendCommandSet(
cmd);
729 FocusMaxMoveNP.
apply();
737void DeepSkyDadAF1::GetFocusParams()
741 CurrentMoveSP.
reset();
742 CurrentHoldSP.
reset();
750 if (readSettleBuffer())
751 SettleBufferNP.
apply();
753 if (readMaxPosition())
756 if (readMaxMovement())
757 FocusMaxMoveNP.
apply();
759 if (readIdleCoilsTimeout())
765 if (readCurrentMove())
766 CurrentMoveSP.
apply();
768 if (readCurrentHold())
769 CurrentHoldSP.
apply();
791void DeepSkyDadAF1::timedMoveCallback()
806 targetPos = targetTicks;
816 int32_t newPosition = 0;
824 newPosition = std::max(0, std::min(
static_cast<int32_t
>(
FocusAbsPosNP[0].getMax()), newPosition));
843 bool rc = readPosition();
862 LOG_INFO(
"Focuser reached requested position.");
871 return sendCommand(
"[STOP]");
876 Focuser::saveConfigItems(fp);
879 FocusMaxMoveNP.
save(fp);
880 SettleBufferNP.
save(fp);
881 CoilsModeSP.
save(fp);
883 CurrentMoveSP.
save(fp);
884 CurrentHoldSP.
save(fp);
889bool DeepSkyDadAF1::sendCommand(
const char *
cmd,
char * res)
891 int nbytes_written = 0, nbytes_read = 0, rc = -1;
893 tcflush(
PortFD, TCIOFLUSH);
901 LOGF_ERROR(
"Serial write error: %s.", errstr);
918 tcflush(
PortFD, TCIOFLUSH);
923bool DeepSkyDadAF1::sendCommandSet(
const char *
cmd)
925 char res[DSD_RES] = {0};
927 if (sendCommand(
cmd, res) ==
false)
930 return strcmp(res,
"(OK)") == 0;
935 char cmd[DSD_RES] = {0};
936 snprintf(
cmd, DSD_RES,
"[SMXP%d]",
static_cast<int>(ticks));
937 return sendCommandSet(
cmd);
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
static void timedMoveHelper(void *context)
const char * getDefaultName() override
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser Move focuser in a specific direction and speed for period of time.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveRelFocuser Move focuser for a relative amount of ticks in a specific direction.
virtual bool saveConfigItems(FILE *fp) override
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusTimerNP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
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
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)
bool update(const ISState states[], const char *const names[], int n)
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)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
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.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
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 IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#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,...)