34 #define MOONLITEDRO_TIMEOUT 3
36 static std::unique_ptr<MoonLiteDRO> dro1(
new MoonLiteDRO(1));
37 static std::unique_ptr<MoonLiteDRO> dro2(
new MoonLiteDRO(2));
43 snprintf(name,
MAXINDINAME,
"MoonLiteDRO #%d", m_ID);
56 IUFillNumber(&StepDelayN[0],
"STEP_DELAY",
"Delay",
"%.f", 1, 5, 1., 1.);
68 IUFillNumber(&TemperatureSettingN[0],
"Calibration",
"Calibration",
"%6.2f", -20, 20, 0.5, 0);
69 IUFillNumber(&TemperatureSettingN[1],
"Coefficient",
"Coefficient",
"%6.2f", -20, 20, 0.5, 0);
82 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
145 if (dro1->isConnected() ==
false)
147 LOG_ERROR(
"You must connect DRO Focuser #1 first before connecting to DRO Focuser #2.");
151 PortFD = dro1->getPortFD();
161 dro2->remoteDisconnect();
192 LOG_INFO(
"Handshake failed. please ensure MoonLite controller is powered and the port is correct.");
198 return "MoonLiteDRO";
201 bool MoonLiteDRO::Ack()
216 PortFD = dro1->getPortFD();
219 LOG_WARN(
"You must connect DRO Focuser #1 first before connecting to DRO Focuser #2.");
227 int nbytes_written = 0, nbytes_read = 0, rc = -1;
232 tcflush(
PortFD, TCIOFLUSH);
240 bool success =
false;
241 while(numChecks < 3 && !success)
247 if(!transmissionSuccess)
250 LOGF_ERROR(
"Handshake Attempt %i, tty transmission error: %s.", numChecks, errstr);
257 LOGF_ERROR(
"Handshake Attempt %i, updatePosition response error: %s.", numChecks, errstr);
260 success = transmissionSuccess && responseSuccess;
265 LOG_INFO(
"Handshake failed after 3 attempts");
269 tcflush(
PortFD, TCIOFLUSH);
271 rc = sscanf(resp,
"%hX#", &pos);
276 bool MoonLiteDRO::updateStepDelay()
278 int nbytes_written = 0, nbytes_read = 0, rc = -1;
281 char cmd[DRO_CMD] = {0};
285 strncpy(
cmd,
":GD#", DRO_CMD);
287 strncpy(
cmd,
":2GD#", DRO_CMD);
291 tcflush(
PortFD, TCIOFLUSH);
296 LOGF_ERROR(
"updateStepDelay error: %s.", errstr);
303 LOGF_ERROR(
"updateStepDelay error: %s.", errstr);
307 tcflush(
PortFD, TCIOFLUSH);
311 rc = sscanf(resp,
"%hX", &speed);
315 int focus_speed = -1;
322 StepDelayN[0].value = focus_speed;
326 LOGF_ERROR(
"Unknown error: focuser step delay value (%s)", resp);
333 bool MoonLiteDRO::updateStepMode()
335 int nbytes_written = 0, nbytes_read = 0, rc = -1;
338 char cmd[DRO_CMD] = {0};
341 strncpy(
cmd,
":GH#", DRO_CMD);
343 strncpy(
cmd,
":2GH#", DRO_CMD);
345 tcflush(
PortFD, TCIOFLUSH);
352 LOGF_ERROR(
"updateStepMode error: %s.", errstr);
359 LOGF_ERROR(
"updateStepMode error: %s.", errstr);
363 tcflush(
PortFD, TCIOFLUSH);
371 if (strcmp(resp,
"FF") == 0)
373 else if (strcmp(resp,
"00") == 0)
377 LOGF_ERROR(
"Unknown error: focuser step value (%s)", resp);
384 bool MoonLiteDRO::updateTemperature()
386 int nbytes_written = 0, nbytes_read = 0, rc = -1;
390 tcflush(
PortFD, TCIOFLUSH);
399 LOGF_ERROR(
"updateTemperature error: %s.", errstr);
406 LOGF_ERROR(
"updateTemperature error: %s.", errstr);
410 tcflush(
PortFD, TCIOFLUSH);
412 resp[nbytes_read - 1] =
'\0';
417 rc = sscanf(resp,
"%X", &temp);
422 TemperatureN[0].value =
static_cast<int16_t
>(temp) / 2.0;
426 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", resp);
433 bool MoonLiteDRO::updatePosition()
435 int nbytes_written = 0, nbytes_read = 0, rc = -1;
437 char resp[DRO_CMD] = {0};
439 char cmd[DRO_CMD] = {0};
442 strncpy(
cmd,
":GP#", DRO_CMD);
444 strncpy(
cmd,
":2GP#", DRO_CMD);
448 tcflush(
PortFD, TCIOFLUSH);
453 LOGF_ERROR(
"updatePosition error: %s.", errstr);
460 LOGF_ERROR(
"updatePosition error: %s.", errstr);
464 tcflush(
PortFD, TCIOFLUSH);
468 rc = sscanf(resp,
"%X", &pos);
476 LOGF_ERROR(
"Unknown error: focuser position value (%s)", resp);
483 bool MoonLiteDRO::isMoving()
485 int nbytes_written = 0, nbytes_read = 0, rc = -1;
487 char resp[DRO_CMD] = {0};
488 char cmd[DRO_CMD] = {0};
491 strncpy(
cmd,
":GI#", DRO_CMD);
493 strncpy(
cmd,
":2GI#", DRO_CMD);
497 tcflush(
PortFD, TCIOFLUSH);
513 tcflush(
PortFD, TCIOFLUSH);
519 if (strcmp(resp,
"01") == 0)
521 else if (strcmp(resp,
"00") == 0)
524 LOGF_ERROR(
"Unknown error: isMoving value (%s)", resp);
528 bool MoonLiteDRO::setTemperatureCalibration(
double calibration)
530 int nbytes_written = 0, rc = -1;
531 char cmd[DRO_CMD] = {0};
533 uint8_t hex =
static_cast<int8_t
>(calibration * 2) & 0xFF;
534 snprintf(
cmd, DRO_CMD,
":PO%02X#", hex);
538 tcflush(
PortFD, TCIOFLUSH);
544 LOGF_ERROR(
"setTemperatureCalibration error: %s.", errstr);
551 bool MoonLiteDRO::setTemperatureCoefficient(
double coefficient)
553 int nbytes_written = 0, rc = -1;
555 char cmd[DRO_CMD] = {0};
556 uint8_t hex =
static_cast<int8_t
>(coefficient * 2) & 0xFF;
557 snprintf(
cmd, DRO_CMD,
":SC%02X#", hex);
561 tcflush(
PortFD, TCIOFLUSH);
566 LOGF_ERROR(
"setTemperatureCoefficient error: %s.", errstr);
575 int nbytes_written = 0, rc = -1;
576 char cmd[DRO_CMD] = {0};
579 snprintf(
cmd, DRO_CMD,
":SP%04X#", ticks);
581 snprintf(
cmd, DRO_CMD,
":2SP%04X#", ticks);
597 bool MoonLiteDRO::gotoAbsPosition(
unsigned int position)
599 int nbytes_written = 0, rc = -1;
601 char cmd[DRO_CMD] = {0};
605 LOGF_ERROR(
"Requested position value out of bound: %d", position);
610 snprintf(
cmd, DRO_CMD,
":SN%04X#", position);
612 snprintf(
cmd, DRO_CMD,
":2SN%04X#", position);
624 memset(
cmd, 0, DRO_CMD);
626 strncpy(
cmd,
":FG#", DRO_CMD);
628 strncpy(
cmd,
":2FG#", DRO_CMD);
636 LOGF_ERROR(
"gotoAbsPosition error: %s.", errstr);
643 bool MoonLiteDRO::setStepMode(FocusStepMode mode)
645 int nbytes_written = 0, rc = -1;
647 char cmd[DRO_CMD] = {0};
649 tcflush(
PortFD, TCIOFLUSH);
654 strncpy(
cmd,
":SH#", DRO_CMD);
656 strncpy(
cmd,
":2SH#", DRO_CMD);
661 strncpy(
cmd,
":SF#", DRO_CMD);
663 strncpy(
cmd,
":2SF#", DRO_CMD);
678 bool MoonLiteDRO::setStepDelay(uint8_t delay)
680 int nbytes_written = 0, rc = -1;
682 char cmd[DRO_CMD] = {0};
689 snprintf(
cmd, DRO_CMD,
":SD%02X#", hex_value);
691 snprintf(
cmd, DRO_CMD,
":2SD%02X#", hex_value);
705 bool MoonLiteDRO::setTemperatureCompensation(
bool enable)
707 int nbytes_written = 0, rc = -1;
709 char cmd[DRO_CMD] = {0};
711 tcflush(
PortFD, TCIOFLUSH);
714 strncpy(
cmd,
":+#", DRO_CMD);
716 strncpy(
cmd,
":-#", DRO_CMD);
723 LOGF_ERROR(
"setTemperatureCompensation error: %s.", errstr);
735 if (strcmp(StepModeSP.
name, name) == 0)
744 if (current_mode == target_mode)
750 if (target_mode == 0)
758 StepModeS[current_mode].s =
ISS_ON;
770 if (strcmp(TemperatureCompensateSP.
name, name) == 0)
775 bool rc = setTemperatureCompensation((TemperatureCompensateS[0].s ==
ISS_ON));
781 TemperatureCompensateS[last_index].s =
ISS_ON;
786 TemperatureCompensateSP.
s =
IPS_OK;
800 if (strcmp(name, TemperatureSettingNP.
name) == 0)
803 if (!setTemperatureCalibration(TemperatureSettingN[0].value) ||
804 !setTemperatureCoefficient(TemperatureSettingN[1].value))
811 TemperatureSettingNP.
s =
IPS_OK;
817 if (strcmp(name, StepDelayNP.
name) == 0)
819 if (setStepDelay(values[0]) ==
false)
836 void MoonLiteDRO::GetFocusParams()
838 if (updatePosition())
841 if (updateTemperature())
844 if (updateStepDelay())
847 if (updateStepMode())
853 targetPos = targetTicks;
857 rc = gotoAbsPosition(targetPos);
869 double newPosition = 0;
877 rc = gotoAbsPosition(newPosition);
896 bool rc = updatePosition();
909 rc = updateTemperature();
912 if (fabs(lastTemperature - TemperatureN[0].value) >= 0.5)
915 lastTemperature = TemperatureN[0].value;
929 LOG_INFO(
"Focuser reached requested position.");
939 char cmd[DRO_CMD] = {0};
941 strncpy(
cmd, (m_ID == 1) ?
":FQ#" :
"#:2FQ#", DRO_CMD);
959 Focuser::saveConfigItems(fp);
const char * getDeviceName() const
void setDeviceName(const char *dev)
Set the device name.
virtual bool Disconnect()
Disconnect from device.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
virtual void setConnected(bool status, IPState state=IPS_OK, const char *msg=nullptr)
Set connection switch status in the client.
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.
Connection::Interface * getActiveConnection()
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool Connect()
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
void addDebugControl()
Add Debug control to the driver.
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
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.
Connection::TCP * tcpConnection
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Connection::Serial * serialConnection
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
const char * getDefaultName() override
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool Disconnect() override
Disconnect from device.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
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....
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.
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_INFO(fmt,...)
#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,...)
#define MOONLITEDRO_TIMEOUT