51 static std::unique_ptr<RainbowRSF> rainbowRSF(
new RainbowRSF());
65 return "Rainbow Astro RSF";
81 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%.2f", -50, 70., 0., 0.);
103 m_MovementTimerActive =
false;
136 if (!strcmp(name, GoHomeSP.
name))
141 LOG_INFO(
"Moving to home position...");
143 LOG_ERROR(
"Failed to move to home position.");
159 LOG_INFO(
"Rainbow Astro is online. Getting focus parameters...");
164 "Error retrieving data from Rainbow Astro, please ensure Rainbow Astro controller is powered and the port is correct.");
174 bool parsePosition(
char *result,
int *pos)
176 const int length = strlen(result);
177 if (length < 6)
return false;
179 char *period = strchr(result + 3,
'.');
180 if (period ==
nullptr)
return false;
183 if (sscanf(result,
":FP%f#", &position) == 1)
186 *pos = position * 1000;
196 char res[DRIVER_LEN] = {0};
228 LOG_INFO(
"Focuser reached home position.");
237 LOG_INFO(
"Focuser reached target position.");
247 else if (
sendCommand(
":Fp#", res, DRIVER_LEN) ==
false)
250 int newPosition { 0 };
251 bool ok = parsePosition(res, &newPosition);
256 constexpr
int TOLERANCE = 1;
257 const int offset = std::abs(
static_cast<int>(
FocusAbsPosN[0].value - m_TargetPosition));
258 bool focuserDone = offset <= TOLERANCE;
265 if (!m_MovementTimerActive)
268 m_MovementTimer.
start();
269 m_MovementTimerActive =
true;
273 const double elapsedSeconds = m_MovementTimer.
elapsed() / 1000.0;
274 if ((elapsedSeconds > 5 && offset < 3) ||
275 (elapsedSeconds > 10 && offset < 6) ||
276 (elapsedSeconds > 60))
279 LOGF_INFO(
"Rainbow focuser timed out: %.1f seconds, offset %d (target %d, position %d)",
280 elapsedSeconds, offset, m_TargetPosition,
static_cast<int>(
FocusAbsPosN[0].value));
287 m_MovementTimerActive =
false;
300 LOG_INFO(
"Focuser reached home position.");
311 LOGF_INFO(
"Focuser reached target position %d at %d.",
312 m_TargetPosition,
static_cast<int>(
FocusAbsPosN[0].value));
330 char res[DRIVER_LEN] = {0};
331 float temperature = 0;
334 strncpy(res,
":FT1+23.5#", DRIVER_LEN);
336 else if (
sendCommand(
":Ft1#", res, DRIVER_LEN) ==
false)
339 if (sscanf(res,
":FT1%g", &temperature) == 1)
341 TemperatureN[0].value = temperature;
357 m_MovementTimerActive =
false;
358 m_TargetPosition = targetTicks;
360 char cmd[DRIVER_LEN] = {0};
361 char res[DRIVER_LEN] = {0};
362 int steps = targetTicks - 8000;
364 snprintf(
cmd, 16,
":Fm%c%04d#", steps >= 0 ?
'+' :
'-', std::abs(steps));
376 m_MovementTimerActive =
false;
378 int relativeTicks = ((dir ==
FOCUS_INWARD) ? -ticks : ticks) * reversed;
379 double newPosition =
FocusAbsPosN[0].value + relativeTicks;
399 m_MovementTimerActive =
false;
400 m_TargetPosition = homePosition;
402 char res[DRIVER_LEN] = {0};
424 LOG_INFO(
"Focuser arrived at home position.");
431 if (m_TemperatureCounter++ == DRIVER_TEMPERATURE_FREQ)
436 if (abs(m_LastTemperature - TemperatureN[0].value) >= 0.05)
439 m_LastTemperature = TemperatureN[0].value;
443 m_TemperatureCounter = 0;
454 if (
cmd ==
nullptr || res ==
nullptr || res_len <= 0)
456 const int cmd_len = strlen(
cmd);
460 tcflush(
PortFD, TCIOFLUSH);
464 int nbytes_written = 0;
470 LOGF_ERROR(
"Serial write error: %s.", errstr);
476 DRIVER_TIMEOUT, &nbytes_read);
477 if (nbytes_read == DRIVER_LEN)
479 res[nbytes_read] = 0;
490 tcflush(
PortFD, TCIOFLUSH);
const char * getDeviceName() const
void addSimulationControl()
Add Simulation control to 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
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
int64_t elapsed() const
Returns the number of milliseconds since this ElapsedTimer was last started.
void start()
Starts this timer. Once started, a timer value can be checked with elapsed().
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.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
Focuser Command Functions.
virtual bool Handshake() override
perform handshake with device to check communication
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
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, unsigned int ticks) override
bool sendCommand(const char *cmd, char *res, int res_len)
Communication Functions.
const char * getDefaultName() override
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.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer 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 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.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#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,...)