34 static constexpr
const int TimerInterval { 500 };
36 static constexpr
const int ReadTimeOut { 1 };
39 static constexpr
const char goto_position {
'g' };
40 static constexpr
const char stop_focuser {
's' };
41 static constexpr
const char read_id_register {
'b' };
42 static constexpr
const char read_id_respons {
'j' };
43 static constexpr
const char read_position {
'p' };
44 static constexpr
const char read_flags {
't' };
45 static constexpr
const char motion_complete {
'c' };
46 static constexpr
const char motion_error {
'r' };
47 static constexpr
const char motion_stopped {
's' };
67 IUFillLight(&FlagsL[STATUS_SERIAL_FRAMING_ERROR],
"SERIAL_FRAMING_ERROR",
"Serial framing error",
IPS_OK);
68 IUFillLight(&FlagsL[STATUS_SERIAL_OVERRUN_ERROR],
"SERIAL_OVERRUN_ERROR",
"Serial overrun error",
IPS_OK);
69 IUFillLight(&FlagsL[STATUS_MOTOR_ENCODE_ERROR],
"MOTOR_ENCODER_ERROR",
"Motor/encoder error",
IPS_OK);
70 IUFillLight(&FlagsL[STATUS_AT_ZERO_POSITION],
"AT_ZERO_POSITION",
"At zero position",
IPS_OK);
71 IUFillLight(&FlagsL[STATUS_AT_MAX_POSITION],
"AT_MAX_POSITION",
"At max. position",
IPS_OK);
75 IUFillNumber(&MotionErrorN[0],
"MOTION_ERROR",
"Motion error",
"%6.0f", -100., 100., 1., 0.);
118 if (!SFacknowledge())
120 LOG_DEBUG(
"SmartFocus is not communicating.");
124 LOG_DEBUG(
"SmartFocus is communicating.");
137 if (strcmp(name, MotionErrorNP.
name) == 0)
157 LOG_DEBUG(
"AbortFocuser: stopping motion");
158 result = send(&stop_focuser,
sizeof(stop_focuser),
"AbortFocuser");
170 position = destination;
176 constexpr
bool Correct_Positions =
true;
177 if (Correct_Positions)
179 const int error = MotionErrorN[0].value;
180 if (destination > position) destination -= error, destination =
std::max(position, destination);
181 if (destination < position) destination += error, destination =
std::min(position, destination);
183 if (destination != position)
186 command[0] = goto_position;
187 command[1] = ((destination >> 8) & 0xFF);
188 command[2] = (destination & 0xFF);
189 LOGF_DEBUG(
"MoveAbsFocuser: destination= %d", destination);
190 tcflush(
PortFD, TCIOFLUSH);
191 if (send(command,
sizeof(command),
"MoveAbsFocuser"))
194 if (recv(&respons,
sizeof(respons),
"MoveAbsFocuser"))
196 LOGF_DEBUG(
"MoveAbsFocuser received echo: %c", respons);
197 if (respons != goto_position)
198 LOGF_ERROR(
"MoveAbsFocuser received unexpected respons: %c (0x02x)", respons,
222 NonBlockingIO(
const char *_device,
const int _fd) : device(_device), fd(_fd), flags(fcntl(_fd, F_GETFL, 0))
227 else if (fcntl(fd, F_SETFL, (flags | O_NONBLOCK)) == -1)
234 if (flags != -1 && fcntl(fd, F_SETFL, flags) == -1)
236 "NonBlockinIO::~NonBlockingIO() fcntl set error: errno=%d",
errno);
259 if (read(
PortFD, &respons,
sizeof(respons)) ==
sizeof(respons))
261 LOGF_DEBUG(
"TimerHit() received character: %c (0x%02x)", respons, respons);
262 if (respons != motion_complete && respons != motion_error && respons != motion_stopped)
263 LOGF_ERROR(
"TimerHit() received unexpected character: %c (0x%02x)", respons,
275 Focuser::saveConfigItems(fp);
280 bool SmartFocus::SFacknowledge()
282 bool success =
false;
287 tcflush(
PortFD, TCIOFLUSH);
288 if (send(&read_id_register,
sizeof(read_id_register),
"SFacknowledge"))
291 if (recv(respons,
sizeof(respons),
"SFacknowledge",
false))
293 LOGF_DEBUG(
"SFacknowledge received: %c%c", respons[0], respons[1]);
294 success = (respons[0] == read_id_register && respons[1] == read_id_respons);
296 LOGF_ERROR(
"SFacknowledge received unexpected respons: %c%c (0x02 0x02x)",
297 respons[0], respons[1], respons[0], respons[1]);
311 tcflush(
PortFD, TCIOFLUSH);
312 if (send(&read_position,
sizeof(read_position),
"SFgetPosition"))
315 if (recv(respons,
sizeof(respons),
"SFgetPosition"))
317 if (respons[0] == read_position)
319 result = (((
static_cast<Position>(respons[1]) << 8) & 0xFF00) |
320 (
static_cast<Position>(respons[2]) & 0x00FF));
321 LOGF_DEBUG(
"SFgetPosition: position=%d", result);
324 LOGF_ERROR(
"SFgetPosition received unexpected respons: %c (0x02x)", respons[0],
332 SmartFocus::Flags SmartFocus::SFgetFlags()
337 tcflush(
PortFD, TCIOFLUSH);
338 if (send(&read_flags,
sizeof(read_flags),
"SFgetFlags"))
341 if (recv(respons,
sizeof(respons),
"SFgetFlags"))
343 if (respons[0] == read_flags)
345 result =
static_cast<Flags
>(respons[1]);
346 LOGF_DEBUG(
"SFgetFlags: flags=0x%02x", result);
349 LOGF_ERROR(
"SFgetFlags received unexpected respons: %c (0x02x)", respons[0],
357 void SmartFocus::SFgetState()
359 const Flags flags = SFgetFlags();
361 FlagsL[STATUS_SERIAL_FRAMING_ERROR].s = (flags & SerFramingError ?
IPS_ALERT :
IPS_OK);
362 FlagsL[STATUS_SERIAL_OVERRUN_ERROR].s = (flags & SerOverrunError ?
IPS_ALERT :
IPS_OK);
363 FlagsL[STATUS_MOTOR_ENCODE_ERROR].s = (flags & MotorEncoderError ?
IPS_ALERT :
IPS_OK);
364 FlagsL[STATUS_AT_ZERO_POSITION].s = (flags & AtZeroPosition ?
IPS_ALERT :
IPS_OK);
365 FlagsL[STATUS_AT_MAX_POSITION].s = (flags & AtMaxPosition ?
IPS_ALERT :
IPS_OK);
368 if ((position = SFgetPosition()) == PositionInvalid)
381 bool SmartFocus::send(
const char *command,
const size_t nbytes,
const char *from,
const bool log_error)
383 int nbytes_written = 0;
385 const bool success = (rc ==
TTY_OK && nbytes_written == (int)nbytes);
387 if (!success && log_error)
391 LOGF_ERROR(
"%s: %s (%d of %d bytes written).", from, errstr, nbytes_written, nbytes);
396 bool SmartFocus::recv(
char *respons,
const size_t nbytes,
const char *from,
const bool log_error)
399 const int rc =
tty_read(
PortFD, respons, nbytes, ReadTimeOut, &nbytes_read);
400 const bool success = (rc ==
TTY_OK && nbytes_read == (int)nbytes);
402 if (!success && log_error)
406 LOGF_ERROR(
"%s: %s (%d of %d bytes read).", errstr, from, nbytes_read, nbytes);
const char * getDeviceName() const
void setCurrentPollingPeriod(uint32_t msec)
setCurrentPollingPeriod Change the current 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)
bool isSimulation() const
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INumberVectorProperty FocusSpeedNP
INumberVectorProperty FocusAbsPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
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.
NonBlockingIO(const char *_device, const int _fd)
virtual bool Handshake() override
perform handshake with device to check communication
const char * getDefaultName() override
virtual IPState MoveAbsFocuser(uint32_t targetPosition) override
MoveFocuser the focuser to an absolute position.
bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
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 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
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 IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
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 IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light 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 IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDMessage(const char *dev, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)
#define DEBUGFDEVICE(device, priority, msg,...)
std::unique_ptr< SmartFocus > smartFocus(new SmartFocus())