34static constexpr const int TimerInterval { 500 };
36static constexpr const int ReadTimeOut { 1 };
39static constexpr const char goto_position {
'g' };
40static constexpr const char stop_focuser {
's' };
41static constexpr const char read_id_register {
'b' };
42static constexpr const char read_id_respons {
'j' };
43static constexpr const char read_position {
'p' };
44static constexpr const char read_flags {
't' };
45static constexpr const char motion_complete {
'c' };
46static constexpr const char motion_error {
'r' };
47static 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.);
116 if (!SFacknowledge())
118 LOG_DEBUG(
"SmartFocus is not communicating.");
122 LOG_DEBUG(
"SmartFocus is communicating.");
135 if (strcmp(name, MotionErrorNP.
name) == 0)
155 LOG_DEBUG(
"AbortFocuser: stopping motion");
156 result = send(&stop_focuser,
sizeof(stop_focuser),
"AbortFocuser");
168 position = destination;
174 constexpr bool Correct_Positions =
true;
175 if (Correct_Positions)
177 const int error = MotionErrorN[0].value;
178 if (destination > position) destination -= error, destination = std::max(position, destination);
179 if (destination < position) destination += error, destination = std::min(position, destination);
181 if (destination != position)
184 command[0] = goto_position;
185 command[1] = ((destination >> 8) & 0xFF);
186 command[2] = (destination & 0xFF);
187 LOGF_DEBUG(
"MoveAbsFocuser: destination= %d", destination);
188 tcflush(
PortFD, TCIOFLUSH);
189 if (send(command,
sizeof(command),
"MoveAbsFocuser"))
192 if (recv(&respons,
sizeof(respons),
"MoveAbsFocuser"))
194 LOGF_DEBUG(
"MoveAbsFocuser received echo: %c", respons);
195 if (respons != goto_position)
196 LOGF_ERROR(
"MoveAbsFocuser received unexpected respons: %c (0x02x)", respons,
220 NonBlockingIO(
const char *_device,
const int _fd) : device(_device), fd(_fd), flags(fcntl(_fd, F_GETFL, 0))
225 else if (fcntl(fd, F_SETFL, (flags | O_NONBLOCK)) == -1)
232 if (flags != -1 && fcntl(fd, F_SETFL, flags) == -1)
234 "NonBlockinIO::~NonBlockingIO() fcntl set error: errno=%d",
errno);
257 if (read(
PortFD, &respons,
sizeof(respons)) ==
sizeof(respons))
259 LOGF_DEBUG(
"TimerHit() received character: %c (0x%02x)", respons, respons);
260 if (respons != motion_complete && respons != motion_error && respons != motion_stopped)
261 LOGF_ERROR(
"TimerHit() received unexpected character: %c (0x%02x)", respons,
273 Focuser::saveConfigItems(fp);
278bool SmartFocus::SFacknowledge()
280 bool success =
false;
285 tcflush(
PortFD, TCIOFLUSH);
286 if (send(&read_id_register,
sizeof(read_id_register),
"SFacknowledge"))
289 if (recv(respons,
sizeof(respons),
"SFacknowledge",
false))
291 LOGF_DEBUG(
"SFacknowledge received: %c%c", respons[0], respons[1]);
292 success = (respons[0] == read_id_register && respons[1] == read_id_respons);
294 LOGF_ERROR(
"SFacknowledge received unexpected respons: %c%c (0x02 0x02x)",
295 respons[0], respons[1], respons[0], respons[1]);
309 tcflush(
PortFD, TCIOFLUSH);
310 if (send(&read_position,
sizeof(read_position),
"SFgetPosition"))
313 if (recv(respons,
sizeof(respons),
"SFgetPosition"))
315 if (respons[0] == read_position)
317 result = (((
static_cast<Position>(respons[1]) << 8) & 0xFF00) |
318 (
static_cast<Position>(respons[2]) & 0x00FF));
319 LOGF_DEBUG(
"SFgetPosition: position=%d", result);
322 LOGF_ERROR(
"SFgetPosition received unexpected respons: %c (0x02x)", respons[0],
330SmartFocus::Flags SmartFocus::SFgetFlags()
335 tcflush(
PortFD, TCIOFLUSH);
336 if (send(&read_flags,
sizeof(read_flags),
"SFgetFlags"))
339 if (recv(respons,
sizeof(respons),
"SFgetFlags"))
341 if (respons[0] == read_flags)
343 result =
static_cast<Flags
>(respons[1]);
344 LOGF_DEBUG(
"SFgetFlags: flags=0x%02x", result);
347 LOGF_ERROR(
"SFgetFlags received unexpected respons: %c (0x02x)", respons[0],
355void SmartFocus::SFgetState()
357 const Flags flags = SFgetFlags();
359 FlagsL[STATUS_SERIAL_FRAMING_ERROR].s = (flags & SerFramingError ?
IPS_ALERT :
IPS_OK);
360 FlagsL[STATUS_SERIAL_OVERRUN_ERROR].s = (flags & SerOverrunError ?
IPS_ALERT :
IPS_OK);
361 FlagsL[STATUS_MOTOR_ENCODE_ERROR].s = (flags & MotorEncoderError ?
IPS_ALERT :
IPS_OK);
362 FlagsL[STATUS_AT_ZERO_POSITION].s = (flags & AtZeroPosition ?
IPS_ALERT :
IPS_OK);
363 FlagsL[STATUS_AT_MAX_POSITION].s = (flags & AtMaxPosition ?
IPS_ALERT :
IPS_OK);
366 if ((position = SFgetPosition()) == PositionInvalid)
369 LOG_ERROR(
"Error while reading SmartFocus position");
379bool SmartFocus::send(
const char *command,
const size_t nbytes,
const char *from,
const bool log_error)
381 int nbytes_written = 0;
383 const bool success = (rc ==
TTY_OK && nbytes_written == (int)nbytes);
385 if (!success && log_error)
389 LOGF_ERROR(
"%s: %s (%d of %d bytes written).", from, errstr, nbytes_written, nbytes);
394bool SmartFocus::recv(
char *respons,
const size_t nbytes,
const char *from,
const bool log_error)
397 const int rc =
tty_read(
PortFD, respons, nbytes, ReadTimeOut, &nbytes_read);
398 const bool success = (rc ==
TTY_OK && nbytes_read == (int)nbytes);
400 if (!success && log_error)
404 LOGF_ERROR(
"%s: %s (%d of %d bytes read).", errstr, from, nbytes_read, nbytes);
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.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSpeedNP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusAbsPosNP
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
NonBlockingIO(const char *_device, const int _fd)
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
const char * getDefaultName() override
virtual IPState MoveAbsFocuser(uint32_t targetPosition) override
MoveFocuser the focuser to an absolute position.
bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
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
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
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...
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.
#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 DEBUGFDEVICE(device, priority, msg,...)
std::unique_ptr< SmartFocus > smartFocus(new SmartFocus())