36 static std::unique_ptr<DeepSkyDadAF2> deepSkyDadAf2(
new DeepSkyDadAF2());
52 IUFillSwitchVector(&StepModeSP, StepModeS, 4,
getDeviceName(),
"Step Mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
67 IUFillNumber(&FocusMaxMoveN[0],
"MAX_MOVE",
"Steps",
"%7.0f", 0, 9999999, 100, 0);
72 IUFillNumber(&SettleBufferN[0],
"SETTLE_BUFFER",
"Period (ms)",
"%5.0f", 0, 99999, 100, 0);
77 IUFillNumber(&IdleCoilsTimeoutN[0],
"IDLE_COILS_TIMEOUT",
"Period (ms)",
"%6.0f", 0, 999999, 1000, 60000);
79 "Idle - coils timeout",
86 IUFillSwitchVector(&CoilsModeSP, CoilsModeS, 3,
getDeviceName(),
"Coils mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
106 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
134 LOG_INFO(
"deepSkyDadAf2 parameters updated, focuser ready for use.");
155 LOG_INFO(
"deepSkyDadAf2 is online. Getting focus parameters...");
160 "Error retrieving data from deepSkyDadAf2, please ensure deepSkyDadAf2 controller is powered and the port is correct.");
166 return "Deep Sky Dad AF2";
169 bool DeepSkyDadAF2::Ack()
173 char res[DSD_RES] = {0};
174 if (!sendCommand(
"[GPOS]", res))
181 int rc = sscanf(res,
"(%d)", &pos);
192 bool DeepSkyDadAF2::readStepMode()
194 char res[DSD_RES] = {0};
196 if (sendCommand(
"[GSTP]", res) ==
false)
199 if (strcmp(res,
"(1)") == 0)
201 else if (strcmp(res,
"(2)") == 0)
203 else if (strcmp(res,
"(4)") == 0)
205 else if (strcmp(res,
"(8)") == 0)
209 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
216 bool DeepSkyDadAF2::readPosition()
218 char res[DSD_RES] = {0};
220 if (sendCommand(
"[GPOS]", res) ==
false)
224 int rc = sscanf(res,
"(%d)", &pos);
230 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
237 bool DeepSkyDadAF2::readMaxMovement()
239 char res[DSD_RES] = {0};
241 if (sendCommand(
"[GMXM]", res) ==
false)
245 int rc = sscanf(res,
"(%d)", &steps);
248 FocusMaxMoveN[0].value = steps;
253 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
260 bool DeepSkyDadAF2::readMaxPosition()
262 char res[DSD_RES] = {0};
264 if (sendCommand(
"[GMXP]", res) ==
false)
268 int rc = sscanf(res,
"(%d)", &steps);
276 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
283 bool DeepSkyDadAF2::readSettleBuffer()
285 char res[DSD_RES] = {0};
287 if (sendCommand(
"[GBUF]", res) ==
false)
290 uint32_t settleBuffer = 0;
291 int rc = sscanf(res,
"(%d)", &settleBuffer);
294 SettleBufferN[0].value = settleBuffer;
299 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
306 bool DeepSkyDadAF2::readIdleCoilsTimeout()
308 char res[DSD_RES] = {0};
310 if (sendCommand(
"[GIDC]", res) ==
false)
314 int rc = sscanf(res,
"(%d)", &ms);
317 IdleCoilsTimeoutN[0].value = ms;
322 LOGF_ERROR(
"Unknown error: idle coils timeout value (%s)", res);
329 bool DeepSkyDadAF2::readCoilsMode()
331 char res[DSD_RES] = {0};
333 if (sendCommand(
"[GCLM]", res) ==
false)
336 if (strcmp(res,
"(0)") == 0)
341 else if (strcmp(res,
"(1)") == 0)
346 else if (strcmp(res,
"(2)") == 0)
353 LOGF_ERROR(
"Unknown error: readCoilsMode value (%s)", res);
360 bool DeepSkyDadAF2::readCurrentMove()
362 char res[DSD_RES] = {0};
364 if (sendCommand(
"[GCMV%]", res) ==
false)
367 if (strcmp(res,
"(25%)") == 0)
372 else if (strcmp(res,
"(50%)") == 0)
377 else if (strcmp(res,
"(75%)") == 0)
382 else if (strcmp(res,
"(100%)") == 0)
390 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
397 bool DeepSkyDadAF2::readCurrentHold()
399 char res[DSD_RES] = {0};
401 if (sendCommand(
"[GCHD%]", res) ==
false)
404 if (strcmp(res,
"(25%)") == 0)
409 else if (strcmp(res,
"(50%)") == 0)
414 else if (strcmp(res,
"(75%)") == 0)
419 else if (strcmp(res,
"(100%)") == 0)
427 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
434 bool DeepSkyDadAF2::readTemperature()
436 char res[DSD_RES] = {0};
438 if (sendCommand(
"[GTMC]", res) ==
false)
442 int rc = sscanf(res,
"(%lf)", &temp);
445 TemperatureN[0].value = temp;
449 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", res);
456 bool DeepSkyDadAF2::isMoving()
458 char res[DSD_RES] = {0};
460 if (sendCommand(
"[GMOV]", res) ==
false)
463 if (strcmp(res,
"(1)") == 0)
465 else if (strcmp(res,
"(0)") == 0)
468 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
474 char cmd[DSD_RES] = {0};
475 snprintf(
cmd, DSD_RES,
"[SPOS%06d]", ticks);
476 return sendCommand(
cmd);
481 char cmd[DSD_RES] = {0};
482 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
483 return sendCommand(
cmd);
488 char cmd[DSD_RES] = {0};
489 char res[DSD_RES] = {0};
490 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
492 if (sendCommand(
cmd, res) ==
false)
495 if(strcmp(res,
"!101)") == 0)
497 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
502 if (sendCommand(
"[SMOV]") ==
false)
513 if (strcmp(StepModeSP.
name, name) == 0)
521 if (current_mode == target_mode)
528 char cmd[DSD_RES] = {0};
532 else if(target_mode == 1)
534 else if(target_mode == 2)
536 else if(target_mode == 3)
539 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
540 bool rc = sendCommandSet(
cmd);
544 StepModeS[current_mode].s =
ISS_ON;
556 if (strcmp(CoilsModeSP.
name, name) == 0)
564 if (coilsModeCurrent == coilsModeTarget)
570 if(coilsModeTarget == 0)
572 else if(coilsModeTarget == 1)
574 else if(coilsModeTarget == 2)
577 char cmd[DSD_RES] = {0};
578 snprintf(
cmd, DSD_RES,
"[SCLM%d]", coilsModeTarget);
580 bool rc = sendCommandSet(
cmd);
584 CoilsModeS[coilsModeCurrent].s =
ISS_ON;
596 if (strcmp(CurrentMoveSP.
name, name) == 0)
604 if (current == targetCurrent)
610 int targetCurrentValue = 75;
611 switch(targetCurrent)
614 targetCurrentValue = 25;
617 targetCurrentValue = 50;
620 targetCurrentValue = 75;
623 targetCurrentValue = 100;
627 char cmd[DSD_RES] = {0};
628 snprintf(
cmd, DSD_RES,
"[SCMV%d%%]", targetCurrentValue);
630 bool rc = sendCommandSet(
cmd);
634 CurrentMoveS[current].s =
ISS_ON;
646 if (strcmp(CurrentHoldSP.
name, name) == 0)
654 if (current == targetCurrent)
660 int targetCurrentValue = 75;
661 switch(targetCurrent)
664 targetCurrentValue = 25;
667 targetCurrentValue = 50;
670 targetCurrentValue = 75;
673 targetCurrentValue = 100;
677 char cmd[DSD_RES] = {0};
678 snprintf(
cmd, DSD_RES,
"[SCHD%d%%]", targetCurrentValue);
680 bool rc = sendCommandSet(
cmd);
684 CurrentHoldS[current].s =
ISS_ON;
704 if (strcmp(name, SettleBufferNP.
name) == 0)
707 char cmd[DSD_RES] = {0};
708 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferN[0].value));
709 bool rc = sendCommandSet(
cmd);
722 if (strcmp(name, IdleCoilsTimeoutNP.
name) == 0)
725 char cmd[DSD_RES] = {0};
726 snprintf(
cmd, DSD_RES,
"[SIDC%06d]",
static_cast<int>(IdleCoilsTimeoutN[0].value));
727 bool rc = sendCommandSet(
cmd);
743 char cmd[DSD_RES] = {0};
744 snprintf(
cmd, DSD_RES,
"[SMXP%d]",
static_cast<int>(
FocusMaxPosN[0].value));
745 bool rc = sendCommandSet(
cmd);
758 if (strcmp(name, FocusMaxMoveNP.
name) == 0)
761 char cmd[DSD_RES] = {0};
762 snprintf(
cmd, DSD_RES,
"[SMXM%d]",
static_cast<int>(FocusMaxMoveN[0].value));
763 bool rc = sendCommandSet(
cmd);
780 void DeepSkyDadAF2::GetFocusParams()
793 if (readSettleBuffer())
796 if (readMaxPosition())
799 if (readMaxMovement())
802 if (readIdleCoilsTimeout())
808 if (readCurrentMove())
811 if (readCurrentHold())
814 if (readTemperature())
837 void DeepSkyDadAF2::timedMoveCallback()
852 targetPos = targetTicks;
862 int32_t newPosition = 0;
889 bool rc = readPosition();
908 LOG_INFO(
"Focuser reached requested position.");
912 rc = readTemperature();
915 if (std::abs(lastTemperature - TemperatureN[0].value) >= 0.5)
918 lastTemperature = TemperatureN[0].value;
927 return sendCommand(
"[STOP]");
932 Focuser::saveConfigItems(fp);
945 bool DeepSkyDadAF2::sendCommand(
const char *
cmd,
char * res)
947 int nbytes_written = 0, nbytes_read = 0, rc = -1;
949 tcflush(
PortFD, TCIOFLUSH);
957 LOGF_ERROR(
"Serial write error: %s.", errstr);
974 tcflush(
PortFD, TCIOFLUSH);
979 bool DeepSkyDadAF2::sendCommandSet(
const char *
cmd)
981 char res[DSD_RES] = {0};
983 if (sendCommand(
cmd, res) ==
false)
986 return strcmp(res,
"(OK)") == 0;
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 ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
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
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
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
Initilize properties initial state and value. The child class must implement this function.
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
static void timedMoveHelper(void *context)
virtual bool Handshake() override
perform handshake with device to check communication
const char * getDeviceName() const
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.
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
INumberVectorProperty FocusTimerNP
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.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
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 IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
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 IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
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 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,...)
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,...)