Instrument Neutral Distributed Interface INDI  1.9.2
myfocuserpro2.cpp
Go to the documentation of this file.
1 /*
2  MyFocuserPro2 Focuser
3  Copyright (c) 2019 Alan Townshend
4 
5  Based on Moonlite focuser
6  Copyright (C) 2013-2019 Jasem Mutlaq (mutlaqja@ikarustech.com)
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 */
23 
24 #include "myfocuserpro2.h"
26 #include "indicom.h"
27 
28 #include <cmath>
29 #include <cstring>
30 #include <memory>
31 
32 #include <termios.h>
33 #include <unistd.h>
34 
35 static std::unique_ptr<MyFocuserPro2> myFocuserPro2(new MyFocuserPro2());
36 
38 {
39  // Can move in Absolute & Relative motions, can AbortFocuser motion, and has variable speed.
43 
45 
46  setVersion(0, 7);
47 }
48 
50 {
52 
53  FocusSpeedN[0].min = 0;
54  FocusSpeedN[0].max = 2;
55  FocusSpeedN[0].value = 1;
56 
57  /* Relative and absolute movement */
58  FocusRelPosN[0].min = 0.;
59  FocusRelPosN[0].max = 50000.;
60  FocusRelPosN[0].value = 0.;
61  FocusRelPosN[0].step = 1000;
62 
63  FocusAbsPosN[0].min = 0.;
64  FocusAbsPosN[0].max = 200000.;
65  FocusAbsPosN[0].value = 0.;
66  FocusAbsPosN[0].step = 1000;
67 
68  FocusMaxPosN[0].min = 1024.;
69  FocusMaxPosN[0].max = 200000.;
70  FocusMaxPosN[0].value = 0.;
71  FocusMaxPosN[0].step = 1000;
72 
73  //Backlash
74  BacklashInStepsN[0].min = 0;
75  BacklashInStepsN[0].max = 512;
76  BacklashInStepsN[0].value = 0;
77  BacklashInStepsN[0].step = 2;
78 
79  BacklashOutStepsN[0].min = 0;
80  BacklashOutStepsN[0].max = 512;
81  BacklashOutStepsN[0].value = 0;
82  BacklashOutStepsN[0].step = 2;
83 
84 
85  // Backlash In
86  IUFillSwitch(&BacklashInS[INDI_ENABLED], "INDI_ENABLED", "On", ISS_OFF);
87  IUFillSwitch(&BacklashInS[INDI_DISABLED], "INDI_DISABLED", "Off", ISS_OFF);
88  IUFillSwitchVector(&BacklashInSP, BacklashInS, 2, getDeviceName(), "Backlash In", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0,
89  IPS_IDLE);
90 
91  IUFillNumber(&BacklashInStepsN[0], "Steps", "", "%3.0f", 0, 512, 2, 0);
92  IUFillNumberVector(&BacklashInStepsNP, BacklashInStepsN, 1, getDeviceName(), "Backlash-In", "", OPTIONS_TAB, IP_RW, 0,
93  IPS_IDLE);
94 
95  // Backlash Out
96  IUFillSwitch(&BacklashOutS[INDI_ENABLED], "INDI_ENABLED", "On", ISS_OFF);
97  IUFillSwitch(&BacklashOutS[INDI_DISABLED], "INDI_DISABLED", "Off", ISS_OFF);
98  IUFillSwitchVector(&BacklashOutSP, BacklashOutS, 2, getDeviceName(), "Backlash Out", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0,
99  IPS_IDLE);
100 
101  IUFillNumber(&BacklashOutStepsN[0], "Steps", "", "%3.0f", 0, 512, 2, 0);
102  IUFillNumberVector(&BacklashOutStepsNP, BacklashOutStepsN, 1, getDeviceName(), "Backlash-Out", "", OPTIONS_TAB, IP_RW, 0,
103  IPS_IDLE);
104 
105  // Focuser temperature
106  IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Celsius", "%6.2f", -40, 80., 0., 0.);
107  IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature", MAIN_CONTROL_TAB,
108  IP_RO, 0, IPS_IDLE);
109 
110  // Temperature Settings
111  IUFillNumber(&TemperatureSettingN[0], "Coefficient", "", "%6.2f", 0, 50, 1, 0);
112  IUFillNumberVector(&TemperatureSettingNP, TemperatureSettingN, 1, getDeviceName(), "T. Settings", "", OPTIONS_TAB, IP_RW, 0,
113  IPS_IDLE);
114 
115  // Compensate for temperature
116  IUFillSwitch(&TemperatureCompensateS[TEMP_COMPENSATE_ENABLE], "TEMP_COMPENSATE_ENABLE", "Enable", ISS_OFF);
117  IUFillSwitch(&TemperatureCompensateS[TEMP_COMPENSATE_DISABLE], "TEMP_COMPENSATE_DISABLE", "Disable", ISS_OFF);
118  IUFillSwitchVector(&TemperatureCompensateSP, TemperatureCompensateS, 2, getDeviceName(), "T. Compensate", "", OPTIONS_TAB,
119  IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
120 
121  // Step Mode
122  IUFillSwitch(&StepModeS[FOCUS_THIRTYSECOND_STEP], "FOCUS_THIRTYSECOND_STEP", "1/32 Step", ISS_OFF);
123  IUFillSwitch(&StepModeS[FOCUS_SIXTEENTH_STEP], "FOCUS_SIXTEENTH_STEP", "1/16 Step", ISS_OFF);
124  IUFillSwitch(&StepModeS[FOCUS_EIGHTH_STEP], "FOCUS_EIGHTH_STEP", "1/8 Step", ISS_OFF);
125  IUFillSwitch(&StepModeS[FOCUS_QUARTER_STEP], "FOCUS_QUARTER_STEP", "1/4 Step", ISS_OFF);
126  IUFillSwitch(&StepModeS[FOCUS_HALF_STEP], "FOCUS_HALF_STEP", "1/2 Step", ISS_OFF);
127  IUFillSwitch(&StepModeS[FOCUS_FULL_STEP], "FOCUS_FULL_STEP", "Full Step", ISS_OFF);
128  IUFillSwitchVector(&StepModeSP, StepModeS, 6, getDeviceName(), "Step Mode", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0,
129  IPS_IDLE);
130 
131 
132  IUFillSwitch(&CoilPowerS[COIL_POWER_ON], "COIL_POWER_ON", "On", ISS_OFF);
133  IUFillSwitch(&CoilPowerS[COIL_POWER_OFF], "COIL_POWER_OFF", "Off", ISS_OFF);
134  IUFillSwitchVector(&CoilPowerSP, CoilPowerS, 2, getDeviceName(), "Coil Power", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0,
135  IPS_IDLE);
136 
137  IUFillSwitch(&DisplayS[DISPLAY_OFF], "DISPLAY_OFF", "Off", ISS_OFF);
138  IUFillSwitch(&DisplayS[DISPLAY_ON], "DISPLAY_ON", "On", ISS_OFF);
139  IUFillSwitchVector(&DisplaySP, DisplayS, 2, getDeviceName(), "Display", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
140 
141 
142  IUFillSwitch(&GotoHomeS[0], "GOTO_HOME", "Go", ISS_OFF);
143  IUFillSwitchVector(&GotoHomeSP, GotoHomeS, 1, getDeviceName(), "Goto Home Position", "", MAIN_CONTROL_TAB, IP_RW,
144  ISR_ATMOST1, 0, IPS_IDLE);
145 
146  setPollingPeriodRange(1000, 30000);
148 
149  tcpConnection->setDefaultHost("192.168.4.1");
151 
152  return true;
153 }
154 
156 {
158 
159  if (isConnected())
160  {
161  defineProperty(&GotoHomeSP);
162  defineProperty(&TemperatureNP);
163  defineProperty(&TemperatureSettingNP);
164  defineProperty(&TemperatureCompensateSP);
165  defineProperty(&BacklashInSP);
166  defineProperty(&BacklashInStepsNP);
167  defineProperty(&BacklashOutSP);
168  defineProperty(&BacklashOutStepsNP);
169  defineProperty(&StepModeSP);
170  defineProperty(&DisplaySP);
171  defineProperty(&CoilPowerSP);
172 
173  setTemperatureCelsius();
174 
175  LOG_INFO("MyFocuserPro2 parameters updated, focuser ready for use.");
176  }
177  else
178  {
179  deleteProperty(GotoHomeSP.name);
180  deleteProperty(TemperatureNP.name);
181  deleteProperty(TemperatureSettingNP.name);
182  deleteProperty(TemperatureCompensateSP.name);
183  deleteProperty(BacklashInSP.name);
184  deleteProperty(BacklashInStepsNP.name);
185  deleteProperty(BacklashOutSP.name);
186  deleteProperty(BacklashOutStepsNP.name);
187  deleteProperty(StepModeSP.name);
188  deleteProperty(DisplaySP.name);
189  deleteProperty(CoilPowerSP.name);
190  }
191 
192  return true;
193 }
194 
196 {
197  if (Ack())
198  {
199  LOG_INFO("MyFocuserPro2 is online. Getting focus parameters...");
200 
201  getStartupValues();
202 
203  return true;
204  }
205 
206  LOG_INFO(
207  "Error retrieving data from MyFocuserPro2, please ensure MyFocuserPro2 controller is powered and the port is correct.");
208  return false;
209 }
210 
212 {
213  return "MyFocuserPro2";
214 }
215 
216 bool MyFocuserPro2::Ack()
217 {
218  int nbytes_written = 0, nbytes_read = 0, rc = -1;
219  char errstr[MAXRBUF];
220  char resp[5] = {0};
221  int firmWareVersion = 0;
222 
223  tcflush(PortFD, TCIOFLUSH);
224 
225  //Try to request the firmware version
226  //Test for success on transmission and response
227  //If either one fails, try again, up to 3 times, waiting 1 sec each time
228  //If that fails, then return false.
229  //If success then check the firmware version
230 
231  int numChecks = 0;
232  bool success = false;
233  while(numChecks < 3 && !success)
234  {
235  numChecks++;
236  sleep(1); //wait 1 second between each test.
237 
238  bool transmissionSuccess = (rc = tty_write(PortFD, ":03#", 4, &nbytes_written)) == TTY_OK;
239  if(!transmissionSuccess)
240  {
241  tty_error_msg(rc, errstr, MAXRBUF);
242  LOGF_ERROR("Handshake Attempt %i, tty transmission error: %s.", numChecks, errstr);
243  }
244 
245  bool responseSuccess = (rc = tty_read(PortFD, resp, 5, ML_TIMEOUT, &nbytes_read)) == TTY_OK;
246  if(!responseSuccess)
247  {
248  tty_error_msg(rc, errstr, MAXRBUF);
249  LOGF_ERROR("Handshake Attempt %i, updatePosition response error: %s.", numChecks, errstr);
250  }
251 
252  success = transmissionSuccess && responseSuccess;
253  }
254 
255  if(!success)
256  {
257  LOG_INFO("Handshake failed after 3 attempts");
258  return false;
259  }
260 
261  tcflush(PortFD, TCIOFLUSH);
262 
263  rc = sscanf(resp, "F%d#", &firmWareVersion);
264 
265  if (rc > 0)
266  {
267  // Minimum check only applicable to serial version
269  {
270  if(firmWareVersion >= MINIMUM_FIRMWARE_VERSION)
271  {
272  LOGF_INFO("MyFP2 reported firmware %d", firmWareVersion);
273  return true;
274 
275  }
276  else
277  {
278  LOGF_ERROR("Invalid Firmware: focuser firmware version value %d, minimum supported is %d", firmWareVersion,
279  MINIMUM_FIRMWARE_VERSION );
280  }
281  }
282  else
283  {
284  LOG_INFO("Connection to network focuser is successful.");
285  return true;
286  }
287  }
288  else
289  {
290  LOGF_ERROR("Invalid Response: focuser firmware version value (%s)", resp);
291  }
292  return false;
293 }
294 
295 bool MyFocuserPro2::readCoilPowerState()
296 {
297  char res[ML_RES] = {0};
298 
299  if (sendCommand(":11#", res) == false)
300  return false;
301 
302  uint32_t temp = 0;
303 
304  int rc = sscanf(res, "O%u#", &temp);
305 
306  if (rc > 0)
307 
308  if(temp == 0)
309  CoilPowerS[COIL_POWER_OFF].s = ISS_ON;
310  else if (temp == 1)
311  CoilPowerS[COIL_POWER_ON].s = ISS_ON;
312  else
313  {
314  LOGF_ERROR("Invalid Response: focuser Coil Power value (%s)", res);
315  return false;
316  }
317  else
318  {
319  LOGF_ERROR("Unknown error: focuser Coil Power value (%s)", res);
320  return false;
321  }
322 
323 
324  return true;
325 }
326 
327 bool MyFocuserPro2::readReverseDirection()
328 {
329  char res[ML_RES] = {0};
330 
331  if (sendCommand(":13#", res) == false)
332  return false;
333 
334  uint32_t temp = 0;
335 
336  int rc = sscanf(res, "R%u#", &temp);
337 
338  if (rc > 0)
339 
340  if(temp == 0)
341  {
343  }
344  else if (temp == 1)
345  {
347  }
348  else
349  {
350  LOGF_ERROR("Invalid Response: focuser Reverse direction value (%s)", res);
351  return false;
352  }
353  else
354  {
355  LOGF_ERROR("Unknown error: focuser Reverse direction value (%s)", res);
356  return false;
357  }
358 
359  return true;
360 }
361 
362 bool MyFocuserPro2::readStepMode()
363 {
364  char res[ML_RES] = {0};
365 
366  if (sendCommand(":29#", res) == false)
367  return false;
368 
369  if (strcmp(res, "S1#") == 0)
370  StepModeS[FOCUS_FULL_STEP].s = ISS_ON;
371  else if (strcmp(res, "S2#") == 0)
372  StepModeS[FOCUS_HALF_STEP].s = ISS_ON;
373  else if (strcmp(res, "S4#") == 0)
374  StepModeS[FOCUS_QUARTER_STEP].s = ISS_ON;
375  else if (strcmp(res, "S8#") == 0)
376  StepModeS[FOCUS_EIGHTH_STEP].s = ISS_ON;
377  else if (strcmp(res, "S16#") == 0)
378  StepModeS[FOCUS_SIXTEENTH_STEP].s = ISS_ON;
379  else if (strcmp(res, "S32#") == 0)
380  StepModeS[FOCUS_THIRTYSECOND_STEP].s = ISS_ON;
381  else
382  {
383  LOGF_ERROR("Unknown error: focuser Step Mode value (%s)", res);
384  return false;
385  }
386 
387  return true;
388 }
389 
390 bool MyFocuserPro2::readTemperature()
391 {
392  char res[ML_RES] = {0};
393 
394  if (sendCommand(":06#", res) == false)
395  return false;
396 
397  double temp = 0;
398  int rc = sscanf(res, "Z%lf#", &temp);
399  if (rc > 0)
400  // Signed hex
401  TemperatureN[0].value = temp;
402  else
403  {
404  LOGF_ERROR("Unknown error: focuser temperature value (%s)", res);
405  return false;
406  }
407 
408  return true;
409 }
410 
411 bool MyFocuserPro2::readTempCompensateEnable()
412 {
413  char res[ML_RES] = {0};
414 
415  if (sendCommand(":24#", res) == false)
416  return false;
417 
418  uint32_t temp = 0;
419 
420  int rc = sscanf(res, "1%u#", &temp);
421 
422  if (rc > 0)
423 
424  if(temp == 0)
425  TemperatureCompensateS[TEMP_COMPENSATE_DISABLE].s = ISS_ON;
426  else if (temp == 1)
427  TemperatureCompensateS[TEMP_COMPENSATE_ENABLE].s = ISS_ON;
428  else
429  {
430  LOGF_ERROR("Invalid Response: focuser T.Compensate value (%s)", res);
431  return false;
432  }
433  else
434  {
435  LOGF_ERROR("Unknown error: focuser T.Compensate value (%s)", res);
436  return false;
437  }
438 
439  return true;
440 }
441 
442 
443 bool MyFocuserPro2::readPosition()
444 {
445  char res[ML_RES] = {0};
446 
447  if (sendCommand(":00#", res) == false)
448  return false;
449 
450  int32_t pos;
451  int rc = sscanf(res, "%*c%d#", &pos);
452 
453  if (rc > 0)
454  FocusAbsPosN[0].value = pos;
455  else
456  {
457  LOGF_ERROR("Unknown error: focuser position value (%s)", res);
458  return false;
459  }
460 
461  return true;
462 }
463 
464 bool MyFocuserPro2::readTempeartureCoefficient()
465 {
466  char res[ML_RES] = {0};
467 
468  if (sendCommand(":26#", res) == false)
469  return false;
470 
471  int32_t val;
472  int rc = sscanf(res, "B%d#", &val);
473 
474  if (rc > 0)
475  TemperatureSettingN[0].value = val;
476  else
477  {
478  LOGF_ERROR("Unknown error: Temperature Coefficient value (%s)", res);
479  return false;
480  }
481 
482  return true;
483 }
484 
485 bool MyFocuserPro2::readSpeed()
486 {
487  char res[ML_RES] = {0};
488 
489  if (sendCommand(":43#", res) == false)
490  return false;
491 
492  int speed = 0;
493  int rc = sscanf(res, "C%d#", &speed);
494 
495  if (rc > 0)
496  {
497  FocusSpeedN[0].value = speed;
498  }
499  else
500  {
501  LOGF_ERROR("Unknown error: focuser speed value (%s)", res);
502  return false;
503  }
504 
505  return true;
506 }
507 
508 bool MyFocuserPro2::readMaxPos()
509 {
510  char res[ML_RES] = {0};
511 
512  if (sendCommand(":08#", res) == false)
513  return false;
514 
515  uint32_t maxPos = 0;
516  int rc = sscanf(res, "M%u#", &maxPos);
517 
518  if (rc > 0)
519  {
520  FocusMaxPosN[0].value = maxPos;
521  Focuser::SyncPresets(maxPos);
522  }
523  else
524  {
525  LOGF_ERROR("Unknown error: focuser max position value (%s)", res);
526  return false;
527  }
528 
529  return true;
530 }
531 
532 bool MyFocuserPro2::readBacklashInSteps()
533 {
534  char res[ML_RES] = {0};
535 
536  if (sendCommand(":78#", res) == false)
537  return false;
538 
539  uint32_t backlash = 0;
540  int rc = sscanf(res, "6%u#", &backlash);
541 
542  if (rc > 0)
543  {
544  BacklashInStepsN[0].value = backlash;
545  }
546  else
547  {
548  BacklashInStepsN[0].value = 0;
549  LOGF_ERROR("Unknown error: focuser Backlash IN value (%s)", res);
550  return false;
551  }
552 
553  return true;
554 }
555 
556 bool MyFocuserPro2::readBacklashInEnabled()
557 {
558  char res[ML_RES] = {0};
559 
560  if (sendCommand(":74#", res) == false)
561  return false;
562 
563  uint32_t temp = 0;
564  int rc = sscanf(res, "4%u#", &temp);
565 
566  if (rc > 0)
567  {
568  if(temp == 0)
569  BacklashInS[INDI_DISABLED].s = ISS_ON;
570  else if (temp == 1)
571  BacklashInS[INDI_ENABLED].s = ISS_ON;
572  else
573  LOGF_ERROR("Unknown Repsonse: focuser Backlash IN enabled (%s)", res);
574  return false;
575  }
576  else
577  {
578  LOGF_ERROR("Unknown error: focuser Backlash IN enabled (%s)", res);
579  return false;
580  }
581 }
582 
583 bool MyFocuserPro2::readBacklashOutSteps()
584 {
585  char res[ML_RES] = {0};
586 
587  if (sendCommand(":80#", res) == false)
588  return false;
589 
590  uint32_t backlash = 0;
591  int rc = sscanf(res, "7%u#", &backlash);
592 
593  if (rc > 0)
594  {
595  BacklashOutStepsN[0].value = backlash;
596  }
597  else
598  {
599  LOGF_ERROR("Unknown error: focuser Backlash OUT value (%s)", res);
600  return false;
601  }
602 
603  return true;
604 }
605 
606 bool MyFocuserPro2::readBacklashOutEnabled()
607 {
608  char res[ML_RES] = {0};
609 
610  if (sendCommand(":76#", res) == false)
611  return false;
612 
613  uint32_t temp = 0;
614  int rc = sscanf(res, "5%u#", &temp);
615 
616  if (rc > 0)
617  {
618  if(temp == 0)
619  BacklashOutS[INDI_DISABLED].s = ISS_ON;
620  else if (temp == 1)
621  BacklashOutS[INDI_ENABLED].s = ISS_ON;
622  else
623  LOGF_ERROR("Unknown response: focuser Backlash OUT enabled (%s)", res);
624  return false;
625  }
626  else
627  {
628  LOGF_ERROR("Unknown error: focuser Backlash OUT enabled (%s)", res);
629  return false;
630  }
631 
632 }
633 
634 bool MyFocuserPro2::readDisplayVisible()
635 {
636  char res[ML_RES] = {0};
637 
638  if (sendCommand(":37#", res) == false)
639  return false;
640 
641  uint32_t temp = 0;
642 
643  int rc = sscanf(res, "D%u#", &temp);
644 
645  if (rc > 0)
646  {
647  if(temp == 0)
648  DisplayS[DISPLAY_OFF].s = ISS_ON;
649  else if (temp == 1)
650  DisplayS[DISPLAY_ON].s = ISS_ON;
651  else
652  {
653  LOGF_ERROR("Invalid Response: focuser Display value (%s)", res);
654  return false;
655  }
656  }
657  else
658  {
659  LOGF_ERROR("Unknown error: focuser Display value (%s)", res);
660  return false;
661  }
662 
663  return true;
664 }
665 
666 bool MyFocuserPro2::isMoving()
667 {
668  char res[ML_RES] = {0};
669 
670  if (sendCommand(":01#", res) == false)
671  return false;
672 
673  uint32_t temp = 0;
674 
675  int rc = sscanf(res, "I%u#", &temp);
676 
677  if (rc > 0)
678  {
679  if(temp == 0)
680  return false;
681  else if (temp == 1)
682  return true;
683  else
684  {
685  LOGF_ERROR("Invalid Response: focuser isMoving value (%s)", res);
686  return false;
687  }
688  }
689  else
690  {
691  LOGF_ERROR("Unknown error: focuser isMoving value (%s)", res);
692  return false;
693  }
694 }
695 
696 
697 bool MyFocuserPro2::setTemperatureCelsius()
698 {
699  char cmd[ML_RES] = {0};
700  snprintf(cmd, ML_RES, ":161#");
701  return sendCommand(cmd);
702 }
703 
704 bool MyFocuserPro2::setTemperatureCoefficient(double coefficient)
705 {
706  char cmd[ML_RES] = {0};
707  int coeff = coefficient;
708  snprintf(cmd, ML_RES, ":22%d#", coeff);
709  return sendCommand(cmd);
710 }
711 
712 bool MyFocuserPro2::SyncFocuser(uint32_t ticks)
713 {
714  char cmd[ML_RES] = {0};
715  snprintf(cmd, ML_RES, ":31%u#", ticks);
716  return sendCommand(cmd);
717 }
718 
719 bool MyFocuserPro2::MoveFocuser(uint32_t position)
720 {
721  char cmd[ML_RES] = {0};
722  if(isMoving())
723  {
724  AbortFocuser();
725  }
726  snprintf(cmd, ML_RES, ":05%u#", position);
727  return sendCommand(cmd);
728 }
729 
730 bool MyFocuserPro2::setBacklashInSteps(int16_t steps)
731 {
732  char cmd[ML_RES] = {0};
733  snprintf(cmd, ML_RES, ":77%d#", steps);
734  return sendCommand(cmd);
735 }
736 
737 bool MyFocuserPro2::setBacklashInEnabled(bool enabled)
738 {
739  char cmd[ML_RES] = {0};
740  snprintf(cmd, ML_RES, ":73%c#", enabled ? '1' : '0');
741  return sendCommand(cmd);
742 }
743 
744 bool MyFocuserPro2::setBacklashOutSteps(int16_t steps)
745 {
746  char cmd[ML_RES] = {0};
747  snprintf(cmd, ML_RES, ":79%d#", steps);
748  return sendCommand(cmd);
749 }
750 
751 bool MyFocuserPro2::setBacklashOutEnabled(bool enabled)
752 {
753  char cmd[ML_RES] = {0};
754  snprintf(cmd, ML_RES, ":75%c#", enabled ? '1' : '0');
755  return sendCommand(cmd);
756 }
757 
758 bool MyFocuserPro2::setCoilPowerState(CoilPower enable)
759 {
760  char cmd[ML_RES] = {0};
761  snprintf(cmd, ML_RES, ":12%d#", static_cast<int>(enable));
762  return sendCommand(cmd);
763 }
764 
765 
767 {
768  char cmd[ML_RES] = {0};
769  snprintf(cmd, ML_RES, ":14%c#", enable ? '1' : '0');
770  return sendCommand(cmd);
771 }
772 
773 
774 bool MyFocuserPro2::setDisplayVisible(DisplayMode enable)
775 {
776  char cmd[ML_RES] = {0};
777  snprintf(cmd, ML_RES, ":36%d#", enable);
778  return sendCommand(cmd);
779 }
780 
781 bool MyFocuserPro2::setGotoHome()
782 {
783  char cmd[ML_RES] = {0};
784  if(isMoving())
785  {
786  AbortFocuser();
787  }
788  snprintf(cmd, ML_RES, ":28#");
789  return sendCommand(cmd);
790 }
791 
792 bool MyFocuserPro2::setStepMode(FocusStepMode mode)
793 {
794  char cmd[ML_RES] = {0};
795  int setMode = 1 << static_cast<int>(mode);
796  snprintf(cmd, ML_RES, ":30%02d#", setMode);
797  return sendCommand(cmd);
798 }
799 
800 bool MyFocuserPro2::setSpeed(uint16_t speed)
801 {
802  char cmd[ML_RES] = {0};
803  snprintf(cmd, ML_RES, ":150%d#", speed);
804  return sendCommand(cmd);
805 }
806 
807 bool MyFocuserPro2::setTemperatureCompensation(bool enable)
808 {
809  char cmd[ML_RES] = {0};
810  snprintf(cmd, ML_RES, ":23%c#", enable ? '1' : '0');
811  return sendCommand(cmd);
812 }
813 
814 bool MyFocuserPro2::ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n)
815 {
816  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
817  {
818  // Focus Step Mode
819  if (strcmp(StepModeSP.name, name) == 0)
820  {
821  int current_mode = IUFindOnSwitchIndex(&StepModeSP);
822 
823  IUUpdateSwitch(&StepModeSP, states, names, n);
824 
825  int target_mode = IUFindOnSwitchIndex(&StepModeSP);
826 
827  if (current_mode == target_mode)
828  {
829  StepModeSP.s = IPS_OK;
830  IDSetSwitch(&StepModeSP, nullptr);
831  }
832 
833  bool rc = setStepMode(static_cast<FocusStepMode>(target_mode));
834  if (!rc)
835  {
836  IUResetSwitch(&StepModeSP);
837  StepModeS[current_mode].s = ISS_ON;
838  StepModeSP.s = IPS_ALERT;
839  IDSetSwitch(&StepModeSP, nullptr);
840  return false;
841  }
842 
843  StepModeSP.s = IPS_OK;
844  IDSetSwitch(&StepModeSP, nullptr);
845  return true;
846  }
847 
848  // Goto Home Position
849  if (strcmp(GotoHomeSP.name, name) == 0)
850  {
851  bool rc = setGotoHome();
852  if (!rc)
853  {
854  IUResetSwitch(&GotoHomeSP);
855  CoilPowerSP.s = IPS_ALERT;
856  IDSetSwitch(&GotoHomeSP, nullptr);
857  return false;
858  }
859 
860  GotoHomeSP.s = IPS_OK;
861  IDSetSwitch(&GotoHomeSP, nullptr);
862  return true;
863  }
864 
865  // Coil Power Mode
866  if (strcmp(CoilPowerSP.name, name) == 0)
867  {
868  int current_mode = IUFindOnSwitchIndex(&CoilPowerSP);
869 
870  IUUpdateSwitch(&CoilPowerSP, states, names, n);
871 
872  int target_mode = IUFindOnSwitchIndex(&CoilPowerSP);
873 
874  if (current_mode == target_mode)
875  {
876  CoilPowerSP.s = IPS_OK;
877  IDSetSwitch(&CoilPowerSP, nullptr);
878  }
879 
880  bool rc = setCoilPowerState(static_cast<CoilPower>(target_mode));
881  if (!rc)
882  {
883  IUResetSwitch(&CoilPowerSP);
884  CoilPowerS[current_mode].s = ISS_ON;
885  CoilPowerSP.s = IPS_ALERT;
886  IDSetSwitch(&CoilPowerSP, nullptr);
887  return false;
888  }
889 
890  CoilPowerSP.s = IPS_OK;
891  IDSetSwitch(&CoilPowerSP, nullptr);
892  return true;
893  }
894 
895 
896  // Display Control
897  if (strcmp(DisplaySP.name, name) == 0)
898  {
899  int current_mode = IUFindOnSwitchIndex(&DisplaySP);
900 
901  IUUpdateSwitch(&DisplaySP, states, names, n);
902 
903  int target_mode = IUFindOnSwitchIndex(&DisplaySP);
904 
905  if (current_mode == target_mode)
906  {
907  DisplaySP.s = IPS_OK;
908  IDSetSwitch(&DisplaySP, nullptr);
909  }
910 
911  bool rc = setDisplayVisible(static_cast<DisplayMode>(target_mode));
912  if (!rc)
913  {
914  IUResetSwitch(&DisplaySP);
915  DisplayS[current_mode].s = ISS_ON;
916  DisplaySP.s = IPS_ALERT;
917  IDSetSwitch(&DisplaySP, nullptr);
918  return false;
919  }
920 
921  DisplaySP.s = IPS_OK;
922  IDSetSwitch(&DisplaySP, nullptr);
923  return true;
924  }
925 
926  // Backlash In Enable
927  if (strcmp(BacklashInSP.name, name) == 0)
928  {
929  int current_mode = IUFindOnSwitchIndex(&BacklashInSP);
930 
931  IUUpdateSwitch(&BacklashInSP, states, names, n);
932 
933  int target_mode = IUFindOnSwitchIndex(&BacklashInSP);
934 
935  if (current_mode == target_mode)
936  {
937  BacklashInSP.s = IPS_OK;
938  IDSetSwitch(&BacklashInSP, nullptr);
939  }
940 
941  bool rc = setBacklashInEnabled(target_mode == INDI_ENABLED);
942  if (!rc)
943  {
944  IUResetSwitch(&BacklashInSP);
945  BacklashInS[current_mode].s = ISS_ON;
946  BacklashInSP.s = IPS_ALERT;
947  IDSetSwitch(&BacklashInSP, nullptr);
948  return false;
949  }
950 
951  BacklashInSP.s = IPS_OK;
952  IDSetSwitch(&BacklashInSP, nullptr);
953  return true;
954  }
955 
956  // Backlash Out Enable
957  if (strcmp(BacklashOutSP.name, name) == 0)
958  {
959  int current_mode = IUFindOnSwitchIndex(&BacklashOutSP);
960 
961  IUUpdateSwitch(&BacklashOutSP, states, names, n);
962 
963  int target_mode = IUFindOnSwitchIndex(&BacklashOutSP);
964 
965  if (current_mode == target_mode)
966  {
967  BacklashOutSP.s = IPS_OK;
968  IDSetSwitch(&BacklashOutSP, nullptr);
969  }
970 
971  bool rc = setBacklashOutEnabled(target_mode == INDI_ENABLED);
972  if (!rc)
973  {
974  IUResetSwitch(&BacklashOutSP);
975  BacklashOutS[current_mode].s = ISS_ON;
976  BacklashOutSP.s = IPS_ALERT;
977  IDSetSwitch(&BacklashOutSP, nullptr);
978  return false;
979  }
980 
981  BacklashOutSP.s = IPS_OK;
982  IDSetSwitch(&BacklashOutSP, nullptr);
983  return true;
984  }
985 
986  // Temperature Compensation Mode
987  if (strcmp(TemperatureCompensateSP.name, name) == 0)
988  {
989  int last_index = IUFindOnSwitchIndex(&TemperatureCompensateSP);
990  IUUpdateSwitch(&TemperatureCompensateSP, states, names, n);
991 
992  bool rc = setTemperatureCompensation((TemperatureCompensateS[0].s == ISS_ON));
993 
994  if (!rc)
995  {
996  TemperatureCompensateSP.s = IPS_ALERT;
997  IUResetSwitch(&TemperatureCompensateSP);
998  TemperatureCompensateS[last_index].s = ISS_ON;
999  IDSetSwitch(&TemperatureCompensateSP, nullptr);
1000  return false;
1001  }
1002 
1003  TemperatureCompensateSP.s = IPS_OK;
1004  IDSetSwitch(&TemperatureCompensateSP, nullptr);
1005  return true;
1006  }
1007  }
1008 
1009  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
1010 }
1011 
1012 bool MyFocuserPro2::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n)
1013 {
1014  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
1015  {
1016  // Temperature Settings
1017  if (strcmp(name, TemperatureSettingNP.name) == 0)
1018  {
1019  IUUpdateNumber(&TemperatureSettingNP, values, names, n);
1020  if (!setTemperatureCoefficient(TemperatureSettingN[0].value))
1021  {
1022  TemperatureSettingNP.s = IPS_ALERT;
1023  IDSetNumber(&TemperatureSettingNP, nullptr);
1024  return false;
1025  }
1026 
1027  TemperatureSettingNP.s = IPS_OK;
1028  IDSetNumber(&TemperatureSettingNP, nullptr);
1029  return true;
1030  }
1031 
1032  // Backlash In
1033  if (strcmp(name, BacklashInStepsNP.name) == 0)
1034  {
1035  IUUpdateNumber(&BacklashInStepsNP, values, names, n);
1036  if (!setBacklashInSteps(BacklashInStepsN[0].value))
1037  {
1038  BacklashInStepsNP.s = IPS_ALERT;
1039  IDSetNumber(&BacklashInStepsNP, nullptr);
1040  return false;
1041  }
1042 
1043  BacklashInStepsNP.s = IPS_OK;
1044  IDSetNumber(&BacklashInStepsNP, nullptr);
1045  return true;
1046  }
1047 
1048  // Backlash Out
1049  if (strcmp(name, BacklashOutStepsNP.name) == 0)
1050  {
1051  IUUpdateNumber(&BacklashOutStepsNP, values, names, n);
1052  if (!setBacklashOutSteps(BacklashOutStepsN[0].value))
1053  {
1054  BacklashOutStepsNP.s = IPS_ALERT;
1055  IDSetNumber(&BacklashOutStepsNP, nullptr);
1056  return false;
1057  }
1058 
1059  BacklashOutStepsNP.s = IPS_OK;
1060  IDSetNumber(&BacklashOutStepsNP, nullptr);
1061  return true;
1062  }
1063 
1064  }
1065 
1066  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
1067 }
1068 
1069 void MyFocuserPro2::getStartupValues()
1070 {
1071  readMaxPos();
1072  readPosition();
1073  readTemperature();
1074  readTempeartureCoefficient();
1075  readSpeed();
1076  readTempCompensateEnable();
1077  readStepMode();
1078  readCoilPowerState();
1079  readDisplayVisible();
1080  readReverseDirection();
1081  readBacklashInEnabled();
1082  readBacklashOutEnabled();
1083  readBacklashInSteps();
1084  readBacklashOutSteps();
1085 }
1086 
1088 {
1089  return setSpeed(speed);
1090 }
1091 
1092 
1094 {
1095  char cmd[ML_RES] = {0};
1096 
1097  snprintf(cmd, ML_RES, ":07%06d#", maxPos);
1098 
1099  if(sendCommand(cmd))
1100  {
1101  Focuser::SyncPresets(maxPos);
1102 
1103  return true;
1104  }
1105  return false;
1106 }
1107 
1108 IPState MyFocuserPro2::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
1109 {
1110  if (speed != static_cast<int>(FocusSpeedN[0].value))
1111  {
1112  if (!setSpeed(speed))
1113  return IPS_ALERT;
1114  }
1115 
1116  // either go all the way in or all the way out
1117  // then use timer to stop
1118  if (dir == FOCUS_INWARD)
1119  MoveFocuser(0);
1120  else
1121  MoveFocuser(FocusMaxPosN[0].value);
1122 
1123  IEAddTimer(duration, &MyFocuserPro2::timedMoveHelper, this);
1124  return IPS_BUSY;
1125 }
1126 
1128 {
1129  static_cast<MyFocuserPro2 *>(context)->timedMoveCallback();
1130 }
1131 
1132 void MyFocuserPro2::timedMoveCallback()
1133 {
1134  AbortFocuser();
1138  FocusTimerN[0].value = 0;
1139  IDSetNumber(&FocusAbsPosNP, nullptr);
1140  IDSetNumber(&FocusRelPosNP, nullptr);
1141  IDSetNumber(&FocusTimerNP, nullptr);
1142 }
1143 
1145 {
1146  targetPos = targetTicks;
1147 
1148  if (!MoveFocuser(targetPos))
1149  return IPS_ALERT;
1150 
1151  return IPS_BUSY;
1152 }
1153 
1155 {
1156  int32_t newPosition = 0;
1157 
1158  if (dir == FOCUS_INWARD)
1159  newPosition = FocusAbsPosN[0].value - ticks;
1160  else
1161  newPosition = FocusAbsPosN[0].value + ticks;
1162 
1163  // Clamp
1164  newPosition = std::max(0, std::min(static_cast<int32_t>(FocusAbsPosN[0].max), newPosition));
1165  if (!MoveFocuser(newPosition))
1166  return IPS_ALERT;
1167 
1168  FocusRelPosN[0].value = ticks;
1170 
1171  return IPS_BUSY;
1172 }
1173 
1175 {
1176  if (!isConnected())
1177  {
1179  return;
1180  }
1181 
1182  bool rc = readPosition();
1183  if (rc)
1184  {
1185  if (fabs(lastPos - FocusAbsPosN[0].value) > 5)
1186  {
1187  IDSetNumber(&FocusAbsPosNP, nullptr);
1188  lastPos = FocusAbsPosN[0].value;
1189  }
1190  }
1191 
1192  rc = readTemperature();
1193  if (rc)
1194  {
1195  if (fabs(lastTemperature - TemperatureN[0].value) >= 0.5)
1196  {
1197  IDSetNumber(&TemperatureNP, nullptr);
1198  lastTemperature = TemperatureN[0].value;
1199  }
1200  }
1201 
1203  {
1204  if (!isMoving())
1205  {
1208  IDSetNumber(&FocusAbsPosNP, nullptr);
1209  IDSetNumber(&FocusRelPosNP, nullptr);
1210  lastPos = FocusAbsPosN[0].value;
1211  LOG_INFO("Focuser reached requested position.");
1212  }
1213  }
1214 
1216 }
1217 
1219 {
1220  return sendCommand(":27#");
1221 }
1222 
1224 {
1225  Focuser::saveConfigItems(fp);
1226 
1227  IUSaveConfigSwitch(fp, &StepModeSP);
1228 
1229  return true;
1230 }
1231 
1232 bool MyFocuserPro2::sendCommand(const char * cmd, char * res)
1233 {
1234  int nbytes_written = 0, nbytes_read = 0, rc = -1;
1235 
1236  tcflush(PortFD, TCIOFLUSH);
1237 
1238  LOGF_DEBUG("CMD <%s>", cmd);
1239 
1240  if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1241  {
1242  char errstr[MAXRBUF] = {0};
1243  tty_error_msg(rc, errstr, MAXRBUF);
1244  LOGF_ERROR("Serial write error: %s.", errstr);
1245  return false;
1246  }
1247 
1248  if (res == nullptr)
1249  {
1250  tcdrain(PortFD);
1251  return true;
1252  }
1253 
1254  if ((rc = tty_nread_section(PortFD, res, ML_RES, ML_DEL, ML_TIMEOUT, &nbytes_read)) != TTY_OK)
1255  {
1256  char errstr[MAXRBUF] = {0};
1257  tty_error_msg(rc, errstr, MAXRBUF);
1258  LOGF_ERROR("Serial read error: %s.", errstr);
1259  return false;
1260  }
1261 
1262  LOGF_DEBUG("RES <%s>", res);
1263 
1264  tcflush(PortFD, TCIOFLUSH);
1265 
1266  return true;
1267 }
MyFocuserPro2::MoveAbsFocuser
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
Definition: myfocuserpro2.cpp:1144
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::FocuserInterface::FocusAbsPosNP
INumberVectorProperty FocusAbsPosNP
Definition: indifocuserinterface.h:282
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
MyFocuserPro2::DISPLAY_ON
@ DISPLAY_ON
Definition: myfocuserpro2.h:40
IPState
IPState
Property state.
Definition: indiapi.h:158
tty_nread_section
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:636
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
min
double min(void)
MyFocuserPro2::timedMoveHelper
static void timedMoveHelper(void *context)
Definition: myfocuserpro2.cpp:1127
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
connectiontcp.h
MyFocuserPro2
Definition: myfocuserpro2.h:30
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
MyFocuserPro2::getDefaultName
const char * getDefaultName() override
Definition: myfocuserpro2.cpp:211
IUFillNumber
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: indidriver.c:348
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
OPTIONS_TAB
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
Definition: defaultdevice.cpp:39
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
MyFocuserPro2::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: myfocuserpro2.cpp:1012
INDI::FocuserInterface::FocusTimerN
INumber FocusTimerN[1]
Definition: indifocuserinterface.h:279
INDI::FocuserInterface::FOCUSER_CAN_ABS_MOVE
@ FOCUSER_CAN_ABS_MOVE
Definition: indifocuserinterface.h:74
MyFocuserPro2::TEMP_COMPENSATE_ENABLE
@ TEMP_COMPENSATE_ENABLE
Definition: myfocuserpro2.h:42
INDI::DefaultDevice::setDefaultPollingPeriod
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
Definition: defaultdevice.cpp:1157
INDI::FocuserInterface::FOCUSER_HAS_VARIABLE_SPEED
@ FOCUSER_HAS_VARIABLE_SPEED
Definition: indifocuserinterface.h:79
MyFocuserPro2::Handshake
virtual bool Handshake() override
Handshake Try to communicate with Focuser and see if there is a valid response.
Definition: myfocuserpro2.cpp:195
MyFocuserPro2::FOCUS_SIXTEENTH_STEP
@ FOCUS_SIXTEENTH_STEP
Definition: myfocuserpro2.h:36
INDI::FocuserInterface::FOCUSER_CAN_SYNC
@ FOCUSER_CAN_SYNC
Definition: indifocuserinterface.h:78
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
MyFocuserPro2::MyFocuserPro2
MyFocuserPro2()
Definition: myfocuserpro2.cpp:37
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
INDI::DefaultDevice::setPollingPeriodRange
void setPollingPeriodRange(uint32_t minimum, uint32_t maximum)
setPollingPeriodRange Set the range permitted by the polling range in milliseconds
Definition: defaultdevice.cpp:1164
MyFocuserPro2::FOCUS_HALF_STEP
@ FOCUS_HALF_STEP
Definition: myfocuserpro2.h:36
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
max
double max(void)
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1421
tty_error_msg
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1135
MyFocuserPro2::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: myfocuserpro2.cpp:1223
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
tty_read
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:462
IEAddTimer
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition: eventloop.c:525
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
type
__le16 type
Definition: pwc-ioctl.h:2
INDI::DefaultDevice::SetTimer
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
Definition: defaultdevice.cpp:865
INDI::Focuser::PortFD
int PortFD
Definition: indifocuser.h:116
MyFocuserPro2::COIL_POWER_OFF
@ COIL_POWER_OFF
Definition: myfocuserpro2.h:38
MyFocuserPro2::SetFocuserSpeed
virtual bool SetFocuserSpeed(int speed) override
SetFocuserSpeed Set Focuser speed.
Definition: myfocuserpro2.cpp:1087
INDI::FocuserInterface::FocusTimerNP
INumberVectorProperty FocusTimerNP
Definition: indifocuserinterface.h:278
tty_write
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:404
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
IUFillSwitchVector
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: indidriver.c:412
IUFillNumberVector
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: indidriver.c:455
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
INDI::Focuser::tcpConnection
Connection::TCP * tcpConnection
Definition: indifocuser.h:114
INDI::FocuserInterface::FocusRelPosN
INumber FocusRelPosN[1]
Definition: indifocuserinterface.h:287
INDI::FocuserInterface::FOCUSER_CAN_REVERSE
@ FOCUSER_CAN_REVERSE
Definition: indifocuserinterface.h:77
ISR_ATMOST1
@ ISR_ATMOST1
Definition: indiapi.h:173
INDI::Focuser::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indifocuser.cpp:120
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
INDI::FocuserInterface::FocusRelPosNP
INumberVectorProperty FocusRelPosNP
Definition: indifocuserinterface.h:286
INDI::Focuser::CONNECTION_SERIAL
@ CONNECTION_SERIAL
Definition: indifocuser.h:55
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
MyFocuserPro2::TEMP_COMPENSATE_DISABLE
@ TEMP_COMPENSATE_DISABLE
Definition: myfocuserpro2.h:42
INDI::Focuser::CONNECTION_TCP
@ CONNECTION_TCP
Definition: indifocuser.h:56
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
MyFocuserPro2::MoveFocuser
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser Move focuser in a specific direction and speed for period of time.
Definition: myfocuserpro2.cpp:1108
MyFocuserPro2::COIL_POWER_ON
@ COIL_POWER_ON
Definition: myfocuserpro2.h:38
MyFocuserPro2::FOCUS_THIRTYSECOND_STEP
@ FOCUS_THIRTYSECOND_STEP
Definition: myfocuserpro2.h:36
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
MyFocuserPro2::FOCUS_QUARTER_STEP
@ FOCUS_QUARTER_STEP
Definition: myfocuserpro2.h:36
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
MyFocuserPro2::FOCUS_FULL_STEP
@ FOCUS_FULL_STEP
Definition: myfocuserpro2.h:36
MyFocuserPro2::FocusStepMode
FocusStepMode
Definition: myfocuserpro2.h:36
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
INDI::FocuserInterface::FocusReverseS
ISwitch FocusReverseS[2]
Definition: indifocuserinterface.h:303
INDI::FocuserInterface::FocusMaxPosN
INumber FocusMaxPosN[1]
Definition: indifocuserinterface.h:291
Connection::TCP::setDefaultHost
void setDefaultHost(const char *addressHost)
Definition: connectiontcp.cpp:231
MyFocuserPro2::AbortFocuser
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: myfocuserpro2.cpp:1218
MyFocuserPro2::DisplayMode
DisplayMode
Definition: myfocuserpro2.h:40
INDI::FocuserInterface::FOCUSER_CAN_ABORT
@ FOCUSER_CAN_ABORT
Definition: indifocuserinterface.h:76
Connection::TCP::setDefaultPort
void setDefaultPort(uint32_t addressPort)
Definition: connectiontcp.cpp:236
MyFocuserPro2::FOCUS_EIGHTH_STEP
@ FOCUS_EIGHTH_STEP
Definition: myfocuserpro2.h:36
myfocuserpro2.h
MyFocuserPro2::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: myfocuserpro2.cpp:155
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
MyFocuserPro2::ReverseFocuser
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition: myfocuserpro2.cpp:766
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
MyFocuserPro2::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: myfocuserpro2.cpp:814
IP_RW
@ IP_RW
Definition: indiapi.h:185
MyFocuserPro2::SyncFocuser
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set the supplied position as the current focuser position.
Definition: myfocuserpro2.cpp:712
MyFocuserPro2::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveRelFocuser Move focuser for a relative amount of ticks in a specific direction.
Definition: myfocuserpro2.cpp:1154
INDI::BaseDevice::INDI_DISABLED
@ INDI_DISABLED
Definition: basedevice.h:65
ISState
ISState
Switch state.
Definition: indiapi.h:148
INDI::Focuser::setSupportedConnections
void setSupportedConnections(const uint8_t &value)
setConnection Set Focuser connection mode. Child class should call this in the constructor before Foc...
Definition: indifocuser.cpp:373
MyFocuserPro2::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: myfocuserpro2.cpp:49
MyFocuserPro2::TimerHit
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: myfocuserpro2.cpp:1174
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1403
Connection::Interface::CONNECTION_SERIAL
@ CONNECTION_SERIAL
Definition: connectioninterface.h:61
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1444
INDI::Focuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:58
MyFocuserPro2::CoilPower
CoilPower
Definition: myfocuserpro2.h:38
tty_write_string
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:454
TTY_OK
@ TTY_OK
Definition: indicom.h:94
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
INDI::Focuser::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: indifocuser.cpp:168
INDI::FocuserInterface::FocusAbsPosN
INumber FocusAbsPosN[1]
Definition: indifocuserinterface.h:283
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
IUFillSwitch
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: indidriver.c:320
MyFocuserPro2::DISPLAY_OFF
@ DISPLAY_OFF
Definition: myfocuserpro2.h:40
INDI::Focuser::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: indifocuser.cpp:145
INDI::DefaultDevice::getActiveConnection
Connection::Interface * getActiveConnection()
Definition: defaultdevice.cpp:1245
INDI::FocuserInterface::FocusSpeedN
INumber FocusSpeedN[1]
Definition: indifocuserinterface.h:269
MyFocuserPro2::SetFocuserMaxPosition
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
Definition: myfocuserpro2.cpp:1093
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151