36static std::unique_ptr<DeepSkyDadAF2> deepSkyDadAf2(
new DeepSkyDadAF2());
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 IdleCoilsTimeoutNP[0].
fill(
"IDLE_COILS_TIMEOUT",
"Period (ms)",
"%6.0f", 0, 999999, 1000, 60000);
84 "Idle - coils timeout",
111 TemperatureNP[0].
fill(
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
139 LOG_INFO(
"deepSkyDadAf2 parameters updated, focuser ready for use.");
160 LOG_INFO(
"deepSkyDadAf2 is online. Getting focus parameters...");
165 "Error retrieving data from deepSkyDadAf2, please ensure deepSkyDadAf2 controller is powered and the port is correct.");
171 return "Deep Sky Dad AF2";
174bool DeepSkyDadAF2::Ack()
178 char res[DSD_RES] = {0};
179 if (!sendCommand(
"[GPOS]", res))
186 int rc = sscanf(res,
"(%d)", &pos);
197bool DeepSkyDadAF2::readStepMode()
199 char res[DSD_RES] = {0};
201 if (sendCommand(
"[GSTP]", res) ==
false)
204 if (strcmp(res,
"(1)") == 0)
206 else if (strcmp(res,
"(2)") == 0)
208 else if (strcmp(res,
"(4)") == 0)
210 else if (strcmp(res,
"(8)") == 0)
214 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
221bool DeepSkyDadAF2::readPosition()
223 char res[DSD_RES] = {0};
225 if (sendCommand(
"[GPOS]", res) ==
false)
229 int rc = sscanf(res,
"(%d)", &pos);
235 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
242bool DeepSkyDadAF2::readMaxMovement()
244 char res[DSD_RES] = {0};
246 if (sendCommand(
"[GMXM]", res) ==
false)
250 int rc = sscanf(res,
"(%d)", &steps);
253 FocusMaxMoveNP[0].setValue(steps);
258 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
265bool DeepSkyDadAF2::readMaxPosition()
267 char res[DSD_RES] = {0};
269 if (sendCommand(
"[GMXP]", res) ==
false)
273 int rc = sscanf(res,
"(%d)", &steps);
281 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
288bool DeepSkyDadAF2::readSettleBuffer()
290 char res[DSD_RES] = {0};
292 if (sendCommand(
"[GBUF]", res) ==
false)
295 uint32_t settleBuffer = 0;
296 int rc = sscanf(res,
"(%d)", &settleBuffer);
299 SettleBufferNP[0].setValue(settleBuffer);
304 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
311bool DeepSkyDadAF2::readIdleCoilsTimeout()
313 char res[DSD_RES] = {0};
315 if (sendCommand(
"[GIDC]", res) ==
false)
319 int rc = sscanf(res,
"(%d)", &ms);
322 IdleCoilsTimeoutNP[0].setValue(ms);
327 LOGF_ERROR(
"Unknown error: idle coils timeout value (%s)", res);
334bool DeepSkyDadAF2::readCoilsMode()
336 char res[DSD_RES] = {0};
338 if (sendCommand(
"[GCLM]", res) ==
false)
341 if (strcmp(res,
"(0)") == 0)
346 else if (strcmp(res,
"(1)") == 0)
351 else if (strcmp(res,
"(2)") == 0)
358 LOGF_ERROR(
"Unknown error: readCoilsMode value (%s)", res);
365bool DeepSkyDadAF2::readCurrentMove()
367 char res[DSD_RES] = {0};
369 if (sendCommand(
"[GCMV%]", res) ==
false)
372 if (strcmp(res,
"(25%)") == 0)
377 else if (strcmp(res,
"(50%)") == 0)
382 else if (strcmp(res,
"(75%)") == 0)
387 else if (strcmp(res,
"(100%)") == 0)
395 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
402bool DeepSkyDadAF2::readCurrentHold()
404 char res[DSD_RES] = {0};
406 if (sendCommand(
"[GCHD%]", res) ==
false)
409 if (strcmp(res,
"(25%)") == 0)
414 else if (strcmp(res,
"(50%)") == 0)
419 else if (strcmp(res,
"(75%)") == 0)
424 else if (strcmp(res,
"(100%)") == 0)
432 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
439bool DeepSkyDadAF2::readTemperature()
441 char res[DSD_RES] = {0};
443 if (sendCommand(
"[GTMC]", res) ==
false)
447 int rc = sscanf(res,
"(%lf)", &temp);
450 TemperatureNP[0].setValue(temp);
454 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", res);
461bool DeepSkyDadAF2::isMoving()
463 char res[DSD_RES] = {0};
465 if (sendCommand(
"[GMOV]", res) ==
false)
468 if (strcmp(res,
"(1)") == 0)
470 else if (strcmp(res,
"(0)") == 0)
473 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
479 char cmd[DSD_RES] = {0};
480 snprintf(
cmd, DSD_RES,
"[SPOS%06d]", ticks);
481 return sendCommand(
cmd);
486 char cmd[DSD_RES] = {0};
487 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
488 return sendCommand(
cmd);
493 char cmd[DSD_RES] = {0};
494 char res[DSD_RES] = {0};
495 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
497 if (sendCommand(
cmd, res) ==
false)
500 if(strcmp(res,
"!101)") == 0)
502 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
507 if (sendCommand(
"[SMOV]") ==
false)
522 StepModeSP.
update(states, names, n);
526 if (current_mode == target_mode)
533 char cmd[DSD_RES] = {0};
537 else if(target_mode == 1)
539 else if(target_mode == 2)
541 else if(target_mode == 3)
544 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
545 bool rc = sendCommandSet(
cmd);
565 CoilsModeSP.
update(states, names, n);
569 if (coilsModeCurrent == coilsModeTarget)
575 if(coilsModeTarget == 0)
577 else if(coilsModeTarget == 1)
579 else if(coilsModeTarget == 2)
582 char cmd[DSD_RES] = {0};
583 snprintf(
cmd, DSD_RES,
"[SCLM%d]", coilsModeTarget);
585 bool rc = sendCommandSet(
cmd);
605 CurrentMoveSP.
update(states, names, n);
609 if (current == targetCurrent)
611 CurrentMoveSP.
apply();
615 int targetCurrentValue = 75;
616 switch(targetCurrent)
619 targetCurrentValue = 25;
622 targetCurrentValue = 50;
625 targetCurrentValue = 75;
628 targetCurrentValue = 100;
632 char cmd[DSD_RES] = {0};
633 snprintf(
cmd, DSD_RES,
"[SCMV%d%%]", targetCurrentValue);
635 bool rc = sendCommandSet(
cmd);
638 CurrentMoveSP.
reset();
641 CurrentMoveSP.
apply();
646 CurrentMoveSP.
apply();
655 CurrentHoldSP.
update(states, names, n);
659 if (current == targetCurrent)
661 CurrentHoldSP.
apply();
665 int targetCurrentValue = 75;
666 switch(targetCurrent)
669 targetCurrentValue = 25;
672 targetCurrentValue = 50;
675 targetCurrentValue = 75;
678 targetCurrentValue = 100;
682 char cmd[DSD_RES] = {0};
683 snprintf(
cmd, DSD_RES,
"[SCHD%d%%]", targetCurrentValue);
685 bool rc = sendCommandSet(
cmd);
688 CurrentHoldSP.
reset();
691 CurrentHoldSP.
apply();
696 CurrentHoldSP.
apply();
711 SettleBufferNP.
update(values, names, n);
712 char cmd[DSD_RES] = {0};
713 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferNP[0].getValue()));
714 bool rc = sendCommandSet(
cmd);
722 SettleBufferNP.
apply();
729 IdleCoilsTimeoutNP.
update(values, names, n);
730 char cmd[DSD_RES] = {0};
731 snprintf(
cmd, DSD_RES,
"[SIDC%06d]",
static_cast<int>(IdleCoilsTimeoutNP[0].getValue()));
732 bool rc = sendCommandSet(
cmd);
740 IdleCoilsTimeoutNP.
apply();
747 FocusMaxMoveNP.
update(values, names, n);
748 char cmd[DSD_RES] = {0};
749 snprintf(
cmd, DSD_RES,
"[SMXM%d]",
static_cast<int>(FocusMaxMoveNP[0].getValue()));
750 bool rc = sendCommandSet(
cmd);
758 FocusMaxMoveNP.
apply();
767void DeepSkyDadAF2::GetFocusParams()
771 CurrentMoveSP.
reset();
772 CurrentHoldSP.
reset();
780 if (readSettleBuffer())
781 SettleBufferNP.
apply();
783 if (readMaxPosition())
786 if (readMaxMovement())
787 FocusMaxMoveNP.
apply();
789 if (readIdleCoilsTimeout())
790 IdleCoilsTimeoutNP.
apply();
795 if (readCurrentMove())
796 CurrentMoveSP.
apply();
798 if (readCurrentHold())
799 CurrentHoldSP.
apply();
801 if (readTemperature())
802 TemperatureNP.
apply();
824void DeepSkyDadAF2::timedMoveCallback()
839 targetPos = targetTicks;
849 int32_t newPosition = 0;
857 newPosition = std::max(0, std::min(
static_cast<int32_t
>(
FocusAbsPosNP[0].getMax()), newPosition));
876 bool rc = readPosition();
895 LOG_INFO(
"Focuser reached requested position.");
899 rc = readTemperature();
902 if (std::abs(lastTemperature - TemperatureNP[0].getValue()) >= 0.5)
904 TemperatureNP.
apply();
905 lastTemperature = TemperatureNP[0].getValue();
914 return sendCommand(
"[STOP]");
919 Focuser::saveConfigItems(fp);
922 FocusMaxMoveNP.
save(fp);
923 SettleBufferNP.
apply();
924 CoilsModeSP.
save(fp);
925 IdleCoilsTimeoutNP.
save(fp);
926 CurrentMoveSP.
save(fp);
927 CurrentHoldSP.
save(fp);
932bool DeepSkyDadAF2::sendCommand(
const char *
cmd,
char * res)
934 int nbytes_written = 0, nbytes_read = 0, rc = -1;
936 tcflush(
PortFD, TCIOFLUSH);
944 LOGF_ERROR(
"Serial write error: %s.", errstr);
961 tcflush(
PortFD, TCIOFLUSH);
966bool DeepSkyDadAF2::sendCommandSet(
const char *
cmd)
968 char res[DSD_RES] = {0};
970 if (sendCommand(
cmd, res) ==
false)
973 return strcmp(res,
"(OK)") == 0;
978 char cmd[DSD_RES] = {0};
979 snprintf(
cmd, DSD_RES,
"[SMXP%d]",
static_cast<int>(ticks));
980 return sendCommandSet(
cmd);
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
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 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 void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool saveConfigItems(FILE *fp) override
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
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.
const char * getDefaultName() override
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
static void timedMoveHelper(void *context)
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
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.
#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,...)