Instrument Neutral Distributed Interface INDI  2.0.2
sestosenso.cpp
Go to the documentation of this file.
1 /*
2  SestoSenso Focuser
3  Copyright (C) 2018 Jasem Mutlaq (mutlaqja@ikarustech.com)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19  Commands and responses:
20 
21  Only use the SM/Sm commands during calibration. Will cause direction reversal!
22  #Sm;xxxxxxx! Set xxxxxxx as min value
23  #SM! Set current position as max
24  #SM;xxxxxxx! Set xxxxxxx as max value (xxxxxxx between 0 to 2097152)
25 
26  #SPxxxx! Set_current_position as xxxx
27  #SC;HOLD;RUN;ACC;DEC! Shell_set_current_supply in HOLD, RUN, ACC, DEC situations (Value must be from 0 to 24, maximum hold value 10)
28  #QM! Query max value
29  #Qm! Query min value
30  #QT! Qeury temperature
31  #QF! Query firmware version
32  #QN! Read the device name -> reply QN;SESTOSENSO!
33  #QP! Query_position
34  #FI! Fast_inward
35  #FO! Fast_outward
36  #SI! Slow_inward
37  #SO! Slow_outward
38  #GTxxxx! Go_to absolute position xxxx
39  #MA! Motion_abort and hold position
40  #MF! Motor free
41  #PS! param_save save current position for next power ON and currents supply
42  #PD! param_to_default , and position to zero
43 
44  Response examples:
45 
46  #QF! 14.06\r
47  #QT! -10.34\r
48  #FI! FIok!\r
49  #FO! FOok!\r
50  #SI! SIok!\r
51  #SO! SOok!\r
52  #GTxxxx! 100\r 200\r 300\r xxxx\r GTok!\r
53  #MA! MAok!\r
54  #MF! MFok!\r
55  #QP! 1530\r
56  #SPxxxx! SPok!\r
57  #SC;HOLD;RUN;ACC;DEC! SCok!\r
58  #PS! PSok!\r
59  #PD! PDok!\r
60 
61  Before to disconnect the COM port, send the #PS! command in order to save the position on internal memory
62 
63 */
64 
65 #include "sestosenso.h"
66 
67 #include "indicom.h"
68 
69 #include <cmath>
70 #include <cstring>
71 #include <memory>
72 
73 #include <termios.h>
74 #include <unistd.h>
75 
76 static std::unique_ptr<SestoSenso> sesto(new SestoSenso());
77 
79 {
80  setVersion(1, 4);
81  // Can move in Absolute & Relative motions, can AbortFocuser motion.
83 }
84 
86 {
88 
89  // Firmware Information
90  IUFillText(&FirmwareT[0], "VERSION", "Version", "");
91  IUFillTextVector(&FirmwareTP, FirmwareT, 1, getDeviceName(), "FOCUS_FIRMWARE", "Firmware", MAIN_CONTROL_TAB, IP_RO, 0,
92  IPS_IDLE);
93 
94  // Focuser temperature
95  IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Celsius", "%6.2f", -50, 70., 0., 0.);
96  IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature", MAIN_CONTROL_TAB,
97  IP_RO, 0, IPS_IDLE);
98 
99  // Focuser calibration
100  IUFillText(&CalibrationMessageT[0], "CALIBRATION", "Calibration stage", "");
101  IUFillTextVector(&CalibrationMessageTP, CalibrationMessageT, 1, getDeviceName(), "CALIBRATION_MESSAGE", "Calibration",
103 
104  IUFillSwitch(&CalibrationS[CALIBRATION_START], "CALIBRATION_START", "Start", ISS_OFF);
105  IUFillSwitch(&CalibrationS[CALIBRATION_NEXT], "CALIBRATION_NEXT", "Next", ISS_OFF);
106  IUFillSwitchVector(&CalibrationSP, CalibrationS, 2, getDeviceName(), "FOCUS_CALIBRATION", "Calibration", MAIN_CONTROL_TAB,
107  IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
108 
109  IUFillSwitch(&FastMoveS[FASTMOVE_IN], "FASTMOVE_IN", "Move In", ISS_OFF);
110  IUFillSwitch(&FastMoveS[FASTMOVE_OUT], "FASTMOVE_OUT", "Move out", ISS_OFF);
111  IUFillSwitch(&FastMoveS[FASTMOVE_STOP], "FASTMOVE_STOP", "Stop", ISS_OFF);
112  IUFillSwitchVector(&FastMoveSP, FastMoveS, 3, getDeviceName(), "FAST_MOVE", "Calibration Move", MAIN_CONTROL_TAB, IP_RW,
113  ISR_1OFMANY, 0, IPS_IDLE);
114 
115  //
116  // Override the default Max. Position to make it Read-Only
117  IUFillNumberVector(&FocusMaxPosNP, FocusMaxPosN, 1, getDeviceName(), "FOCUS_MAX", "Max. Position", MAIN_CONTROL_TAB, IP_RO,
118  0, IPS_IDLE);
119 
120  // Relative and absolute movement
121  FocusRelPosN[0].min = 0.;
122  FocusRelPosN[0].max = 50000.;
123  FocusRelPosN[0].value = 0;
124  FocusRelPosN[0].step = 1000;
125 
126  FocusAbsPosN[0].min = 0.;
127  FocusAbsPosN[0].max = 2097152.;
128  FocusAbsPosN[0].value = 0;
129  FocusAbsPosN[0].step = 1000;
130 
131  FocusMaxPosN[0].value = 2097152;
132 
133  addAuxControls();
134 
136 
137  m_MotionProgressTimer.callOnTimeout(std::bind(&SestoSenso::checkMotionProgressCallback, this));
138  m_MotionProgressTimer.setSingleShot(true);
139 
140  return true;
141 }
142 
144 {
146 
147  if (isConnected())
148  {
149  // Only define temperature if there is a probe
150  if (updateTemperature())
151  defineProperty(&TemperatureNP);
152  defineProperty(&FirmwareTP);
153  IUSaveText(&CalibrationMessageT[0], "Press START to begin the Calibration");
154  defineProperty(&CalibrationMessageTP);
155  defineProperty(&CalibrationSP);
156 
157  if (getStartupValues())
158  LOG_INFO("SestoSenso parameters updated, focuser ready for use.");
159  else
160  LOG_WARN("Failed to inquire parameters. Check logs.");
161  }
162  else
163  {
164  if (TemperatureNP.s == IPS_OK)
165  deleteProperty(TemperatureNP.name);
166  deleteProperty(FirmwareTP.name);
167  deleteProperty(CalibrationMessageTP.name);
168  deleteProperty(CalibrationSP.name);
169  }
170 
171  return true;
172 }
173 
175 {
176  if (Ack())
177  {
178  LOG_INFO("SestoSenso is online. Getting focus parameters...");
179  return true;
180  }
181 
182  LOG_INFO(
183  "Error retrieving data from SestoSenso, please ensure SestoSenso controller is powered and the port is correct.");
184  return false;
185 }
186 
188 {
189  // Save current position to memory.
190  if (isSimulation() == false)
191  sendCommand("#PS!");
192 
193  return INDI::Focuser::Disconnect();
194 }
195 
197 {
198  return "Sesto Senso";
199 }
200 
201 bool SestoSenso::Ack()
202 {
203  char res[SESTO_LEN] = {0};
204 
205  if (isSimulation())
206  strncpy(res, "1.0 Simulation", SESTO_LEN);
207  else if (sendCommand("#QF!", res) == false)
208  return false;
209 
210  IUSaveText(&FirmwareT[0], res);
211 
212  return true;
213 }
214 
215 bool SestoSenso::updateTemperature()
216 {
217  char res[SESTO_LEN] = {0};
218  double temperature = 0;
219 
220  if (isSimulation())
221  strncpy(res, "23.45", SESTO_LEN);
222  else if (sendCommand("#QT!", res) == false)
223  return false;
224 
225  try
226  {
227  temperature = std::stod(res);
228  }
229  catch(...)
230  {
231  LOGF_WARN("Failed to process temperature response: %s (%d bytes)", res, strlen(res));
232  return false;
233  }
234 
235  if (temperature > 90)
236  return false;
237 
238  TemperatureN[0].value = temperature;
239  TemperatureNP.s = IPS_OK;
240 
241  return true;
242 }
243 
244 bool SestoSenso::updateMaxLimit()
245 {
246  char res[SESTO_LEN] = {0};
247 
248  if (isSimulation())
249  return true;
250 
251  if (sendCommand("#QM!", res) == false)
252  return false;
253 
254  int maxLimit = 0;
255 
256  sscanf(res, "QM;%d!", &maxLimit);
257 
258  if (maxLimit > 0)
259  {
260  FocusMaxPosN[0].max = maxLimit;
261  if (FocusMaxPosN[0].value > maxLimit)
262  FocusMaxPosN[0].value = maxLimit;
263 
264  FocusAbsPosN[0].min = 0;
265  FocusAbsPosN[0].max = maxLimit;
266  FocusAbsPosN[0].value = 0;
267  FocusAbsPosN[0].step = (FocusAbsPosN[0].max - FocusAbsPosN[0].min) / 50.0;
268 
269  FocusRelPosN[0].min = 0.;
270  FocusRelPosN[0].max = FocusAbsPosN[0].step * 10;
271  FocusRelPosN[0].value = 0;
272  FocusRelPosN[0].step = FocusAbsPosN[0].step;
273 
276 
279  return true;
280  }
281 
283  return false;
284 }
285 
286 bool SestoSenso::updatePosition()
287 {
288  char res[SESTO_LEN] = {0};
289  if (isSimulation())
290  snprintf(res, SESTO_LEN, "%d", static_cast<uint32_t>(FocusAbsPosN[0].value));
291  else if (sendCommand("#QP!", res) == false)
292  return false;
293 
294  try
295  {
296  FocusAbsPosN[0].value = std::stoi(res);
298  return true;
299  }
300  catch(...)
301  {
302  LOGF_WARN("Failed to process position response: %s (%d bytes)", res, strlen(res));
304  return false;
305  }
306 }
307 
308 bool SestoSenso::isMotionComplete()
309 {
310  char res[SESTO_LEN] = {0};
311 
312  if (isSimulation())
313  {
314  int32_t nextPos = FocusAbsPosN[0].value;
315  int32_t targPos = static_cast<int32_t>(targetPos);
316 
317  if (targPos > nextPos)
318  nextPos += 250;
319  else if (targPos < nextPos)
320  nextPos -= 250;
321 
322  if (abs(nextPos - targPos) < 250)
323  nextPos = targetPos;
324  else if (nextPos < 0)
325  nextPos = 0;
326  else if (nextPos > FocusAbsPosN[0].max)
327  nextPos = FocusAbsPosN[0].max;
328 
329  snprintf(res, SESTO_LEN, "%d", nextPos);
330  }
331  else
332  {
333  int nbytes_read = 0;
334 
335  //while (rc != TTY_TIME_OUT)
336  //{
337  int rc = tty_read_section(PortFD, res, SESTO_STOP_CHAR, 1, &nbytes_read);
338  if (rc == TTY_OK)
339  {
340  res[nbytes_read - 1] = 0;
341 
342 
343  if (!strcmp(res, "GTok!"))
344  return true;
345 
346  try
347  {
348  uint32_t newPos = std::stoi(res);
349  FocusAbsPosN[0].value = newPos;
350  }
351  catch (...)
352  {
353  LOGF_WARN("Failed to process motion response: %s (%d bytes)", res, strlen(res));
354  }
355  }
356  //}
357  }
358 
359  return false;
360 }
361 
362 bool SestoSenso::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
363 {
364  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
365  {
366 
367  // Calibrate focuser
368  if (!strcmp(name, CalibrationSP.name))
369  {
370  char res[SESTO_LEN] = {0};
371  int current_switch = 0;
372 
373  CalibrationSP.s = IPS_BUSY;
374  //IDSetSwitch(&CalibrationSP, nullptr);
375  IUUpdateSwitch(&CalibrationSP, states, names, n);
376 
377  current_switch = IUFindOnSwitchIndex(&CalibrationSP);
378  CalibrationS[current_switch].s = ISS_ON;
379  IDSetSwitch(&CalibrationSP, nullptr);
380 
381  if (current_switch == CALIBRATION_START)
382  {
383  if (cStage == Idle || cStage == Complete )
384  {
385  // Start the calibration process
386  LOG_INFO("Start Calibration");
387  CalibrationSP.s = IPS_BUSY;
388  IDSetSwitch(&CalibrationSP, nullptr);
389 
390  //
391  // Unlock the motor to allow manual movement of the focuser
392  //
393  if (sendCommand("#MF!") == false)
394  return false;
395 
396  IUSaveText(&CalibrationMessageT[0], "Move focuser manually to the middle then press NEXT");
397  IDSetText(&CalibrationMessageTP, nullptr);
398 
399  // Set next step
400  cStage = GoToMiddle;
401  }
402  else
403  {
404  LOG_INFO("Already started calibration. Proceed to next step.");
405  IUSaveText(&CalibrationMessageT[0], "Already started. Proceed to NEXT.");
406  IDSetText(&CalibrationMessageTP, nullptr);
407  }
408  }
409  else if (current_switch == CALIBRATION_NEXT)
410  {
411  if (cStage == GoToMiddle)
412  {
413  defineProperty(&FastMoveSP);
414  IUSaveText(&CalibrationMessageT[0], "Move In/Move Out/Stop to MIN position then press NEXT");
415  IDSetText(&CalibrationMessageTP, nullptr);
416  cStage = GoMinimum;
417  }
418  else if (cStage == GoMinimum)
419  {
420  // Minimum position needs setting
421  if (sendCommand("#Sm;0!") == false)
422  return false;
423 
424  IUSaveText(&CalibrationMessageT[0], "Move In/Move Out/Stop to MAX position then press NEXT");
425  IDSetText(&CalibrationMessageTP, nullptr);
426  cStage = GoMaximum;
427  }
428  else if (cStage == GoMaximum)
429  {
430  // Maximum position needs setting and save
431  // Do not split these commands.
432 
433  if (sendCommand("#SM!", res) == false)
434  return false;
435  if (sendCommand("#PS!") == false)
436  return false;
437  //
438  // MAX value is in maxLimit
439  // MIN value is 0
440  //
441  int maxLimit = 0;
442  sscanf(res, "SM;%d!", &maxLimit);
443  LOGF_INFO("MAX setting is %d", maxLimit);
444 
445  FocusMaxPosN[0].max = maxLimit;
446  FocusMaxPosN[0].value = maxLimit;
447 
448  FocusAbsPosN[0].min = 0;
449  FocusAbsPosN[0].max = maxLimit;
450  FocusAbsPosN[0].value = maxLimit;
451  FocusAbsPosN[0].step = (FocusAbsPosN[0].max - FocusAbsPosN[0].min) / 50.0;
452 
453  FocusRelPosN[0].min = 0.;
454  FocusRelPosN[0].max = FocusAbsPosN[0].step * 10;
455  FocusRelPosN[0].value = 0;
456  FocusRelPosN[0].step = FocusAbsPosN[0].step;
457 
462 
463  IUSaveText(&CalibrationMessageT[0], "Calibration Completed.");
464  IDSetText(&CalibrationMessageTP, nullptr);
465 
466  deleteProperty(FastMoveSP.name);
467  cStage = Complete;
468 
469  LOG_INFO("Calibration completed");
470  CalibrationSP.s = IPS_OK;
471  IDSetSwitch(&CalibrationSP, nullptr);
472  CalibrationS[current_switch].s = ISS_OFF;
473  IDSetSwitch(&CalibrationSP, nullptr);
474  }
475  else
476  {
477  IUSaveText(&CalibrationMessageT[0], "Calibration not in process");
478  IDSetText(&CalibrationMessageTP, nullptr);
479  }
480 
481  }
482  return true;
483  }
484  else if (!strcmp(name, FastMoveSP.name))
485  {
486  IUUpdateSwitch(&FastMoveSP, states, names, n);
487  int current_switch = IUFindOnSwitchIndex(&FastMoveSP);
488 
489  switch (current_switch)
490  {
491  case FASTMOVE_IN:
492  if (sendCommand("#FI!") == false)
493  {
494  return false;
495  }
496  break;
497  case FASTMOVE_OUT:
498  if (sendCommand("#FO!") == false)
499  {
500  return false;
501  }
502  break;
503  case FASTMOVE_STOP:
504  if (sendCommand("#MA!") == false)
505  {
506  return false;
507  }
508  break;
509  default:
510  break;
511  }
512 
513  FastMoveSP.s = IPS_BUSY;
514  IDSetSwitch(&FastMoveSP, nullptr);
515  return true;
516  }
517 
518  }
519  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
520 }
521 
522 IPState SestoSenso::MoveAbsFocuser(uint32_t targetTicks)
523 {
524  targetPos = targetTicks;
525 
526  char cmd[SESTO_LEN] = {0};
527  snprintf(cmd, 16, "#GT%u!", targetTicks);
528  if (isSimulation() == false)
529  {
530  if (sendCommand(cmd) == false)
531  return IPS_ALERT;
532  }
533 
534  m_MotionProgressTimer.start(10);
535  return IPS_BUSY;
536 }
537 
539 {
540  int reversed = (IUFindOnSwitchIndex(&FocusReverseSP) == INDI_ENABLED) ? -1 : 1;
541  int relativeTicks = ((dir == FOCUS_INWARD) ? -ticks : ticks) * reversed;
542  double newPosition = FocusAbsPosN[0].value + relativeTicks;
543 
544  bool rc = MoveAbsFocuser(newPosition);
545 
546  return (rc ? IPS_BUSY : IPS_ALERT);
547 }
548 
550 {
551  m_MotionProgressTimer.stop();
552 
553  if (isSimulation())
554  return true;
555 
556  return sendCommand("#MA!");
557 }
558 
559 //
560 // This timer function is initiated when a GT command has been issued
561 // A timer will call this function on a regular interval during the motion
562 // Modified the code to exit when motion is complete
563 //
564 void SestoSenso::checkMotionProgressCallback()
565 {
566  if (isMotionComplete())
567  {
570  IDSetNumber(&FocusRelPosNP, nullptr);
571  IDSetNumber(&FocusAbsPosNP, nullptr);
572  lastPos = FocusAbsPosN[0].value;
573  LOG_INFO("Focuser reached requested position.");
574  return;
575  }
576  else
577  IDSetNumber(&FocusAbsPosNP, nullptr);
578 
579  lastPos = FocusAbsPosN[0].value;
580 
581  m_MotionProgressTimer.start(250);
582 }
583 
585 {
586  if (!isConnected() || FocusAbsPosNP.s == IPS_BUSY || FocusRelPosNP.s == IPS_BUSY || CalibrationSP.s == IPS_BUSY)
587  {
589  return;
590  }
591 
592  bool rc = updatePosition();
593  if (rc)
594  {
595  if (fabs(lastPos - FocusAbsPosN[0].value) > 0)
596  {
597  IDSetNumber(&FocusAbsPosNP, nullptr);
598  lastPos = FocusAbsPosN[0].value;
599  }
600  }
601 
602  if (m_TemperatureCounter++ == SESTO_TEMPERATURE_FREQ)
603  {
604  rc = updateTemperature();
605  if (rc)
606  {
607  if (fabs(lastTemperature - TemperatureN[0].value) >= 0.1)
608  {
609  IDSetNumber(&TemperatureNP, nullptr);
610  lastTemperature = TemperatureN[0].value;
611  }
612  }
613  m_TemperatureCounter = 0; // Reset the counter
614  }
615 
617 }
618 
619 bool SestoSenso::getStartupValues()
620 {
621  bool rc1 = updatePosition();
622  if (rc1)
623  IDSetNumber(&FocusAbsPosNP, nullptr);
624 
625  if (updateMaxLimit() == false)
626  LOG_WARN("Check you have the latest SestoSenso firmware. Focuser requires calibration.");
627 
628  return (rc1);
629 }
630 
631 bool SestoSenso::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
632 {
633  int nbytes_written = 0, nbytes_read = 0, rc = -1;
634 
635  tcflush(PortFD, TCIOFLUSH);
636 
637  if (cmd_len > 0)
638  {
639  char hex_cmd[SESTO_LEN * 3] = {0};
640  hexDump(hex_cmd, cmd, cmd_len);
641  LOGF_DEBUG("CMD <%s>", hex_cmd);
642  rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
643  }
644  else
645  {
646  LOGF_DEBUG("CMD <%s>", cmd);
647  rc = tty_write_string(PortFD, cmd, &nbytes_written);
648  }
649 
650  if (rc != TTY_OK)
651  {
652  char errstr[MAXRBUF] = {0};
653  tty_error_msg(rc, errstr, MAXRBUF);
654  LOGF_ERROR("Serial write error: %s.", errstr);
655  return false;
656  }
657 
658  if (res == nullptr)
659  return true;
660 
661  if (res_len > 0)
662  rc = tty_read(PortFD, res, res_len, SESTO_TIMEOUT, &nbytes_read);
663  else
664  {
665  rc = tty_nread_section(PortFD, res, SESTO_LEN, SESTO_STOP_CHAR, SESTO_TIMEOUT, &nbytes_read);
666  res[nbytes_read - 1] = 0;
667  }
668 
669  if (rc != TTY_OK)
670  {
671  char errstr[MAXRBUF] = {0};
672  tty_error_msg(rc, errstr, MAXRBUF);
673  LOGF_ERROR("Serial read error: %s.", errstr);
674  return false;
675  }
676 
677  if (res_len > 0)
678  {
679  char hex_res[SESTO_LEN * 3] = {0};
680  hexDump(hex_res, res, res_len);
681  LOGF_DEBUG("RES <%s>", hex_res);
682  }
683  else
684  {
685  LOGF_DEBUG("RES <%s>", res);
686  }
687 
688  tcflush(PortFD, TCIOFLUSH);
689 
690  return true;
691 }
692 
693 void SestoSenso::hexDump(char * buf, const char * data, int size)
694 {
695  for (int i = 0; i < size; i++)
696  sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
697 
698  if (size > 0)
699  buf[3 * size - 1] = '\0';
700 }
701 
702 bool SestoSenso::ReverseFocuser(bool enable)
703 {
704  INDI_UNUSED(enable);
705  return false;
706 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool Disconnect()
Disconnect from device.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in 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
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
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.
Definition: indifocuser.cpp:42
void setSingleShot(bool singleShot)
Set whether the timer is a single-shot timer.
Definition: inditimer.cpp:109
void callOnTimeout(const std::function< void()> &callback)
Definition: inditimer.cpp:76
void start()
Starts or restarts the timer with the timeout specified in interval.
Definition: inditimer.cpp:82
void stop()
Stops the timer.
Definition: inditimer.cpp:97
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: sestosenso.cpp:549
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: sestosenso.cpp:362
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition: sestosenso.cpp:702
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
Definition: sestosenso.cpp:522
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: sestosenso.cpp:85
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: sestosenso.cpp:584
const char * getDefaultName() override
Definition: sestosenso.cpp:196
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: sestosenso.cpp:538
virtual bool Disconnect() override
Disconnect from device.
Definition: sestosenso.cpp:187
virtual bool Handshake() override
perform handshake with device to check communication
Definition: sestosenso.cpp:174
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: sestosenso.cpp:143
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
double max(void)
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:566
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:424
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:482
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
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
Definition: indicom.c:666
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
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.
Definition: indidevapi.c:272
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:291
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
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.
Definition: indidevapi.c:158
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition: indidevapi.c:198
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.
Definition: indidevapi.c:180
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.
Definition: indidevapi.c:235
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
Definition: indidriver.c:1296
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
#define LOG_WARN(txt)
Definition: indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define MAXRBUF
Definition: indiserver.cpp:102
__u8 cmd[4]
Definition: pwc-ioctl.h:2
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250