Instrument Neutral Distributed Interface INDI  1.9.5
focuslynxbase.cpp
Go to the documentation of this file.
1 /*
2  Focus Lynx INDI driver
3  Copyright (C) 2015 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 
20 #include "focuslynxbase.h"
21 
22 /************************************************************************************
23  *
24 * ***********************************************************************************/
25 FocusLynxBase::FocusLynxBase(const char *target)
26 {
27  INDI_UNUSED(target);
28 }
29 
30 /************************************************************************************
31  *
32 * ***********************************************************************************/
34 {
36 
37  lynxModels["Optec TCF-Lynx 2"] = "OA";
38  lynxModels["Optec TCF-Lynx 3"] = "OB";
39 
40  // "OC" is now reserved, it is hard coded into focusers that use it
41  // Allthough it can be selected it should not be
42  // lynxModels["Optec TCF-Lynx 2 with Extended Travel"] = "OC";
43  lynxModels["Optec Fast Focus Secondary Focuser"] = "OD";
44 
45  // "OE" and "OF" are reserved, no models that are not "OA" or "OB" have been deployed
46  // lynxModels["Optec TCF-S Classic converted"] = "OE";
47  // lynxModels["Optec TCF-S3 Classic converted"] = "OF";
48 
49  // "OG" Gemini is reserved. It is used to identify the Optec Gemini
50  // lynxModels["Optec Gemini (reserved for future use)"] = "OG";
51 
52  lynxModels["Optec Leo"] = "OI";
53  lynxModels["Optec Leo High-Torque"] = "OJ";
54  lynxModels["Optec Sagitta"] = "OK";
55  lynxModels["Optec Sagitta 2"] = "OL";
56 
57  // These are generic for all Optec QuickSync and FeatherTouch HSM models
58  lynxModels["QuickSync / HSM Hi-Torque"] = "FA";
59  lynxModels["QuickSync / HSM Hi-Speed"] = "FB";
60 
61  // "FC" is reserved, it has not been deployed and is covered by "FA" and "FB"
62  // lynxModels["FocusLynx QuickSync SV (reserved for future use)"] = "FC";
63 
64  // These are generic for all Optec DirectSync and FeatherTouch PDMS models
65  lynxModels["DirectSync / PDMS Hi-Torque"] = "FD";
66  lynxModels["DirectSync / PDMS Hi-Speed"] = "FF";
67 
68  // JM 2019-09-27: This was added after the discussion here
69  // https://www.indilib.org/forum/focusers-filter-wheels/5739-starlight-instruments-focuser-boss-ii-hsm20.html
70  // DVN 2021-11-15: Covered by the generic Device Type FA and FB.
71  // Continued: duplicating device types can result in the wrong type being displayed in the selection box
72  // lynxModels["FeatureTouch HSM Hi-Torque"] = "FA";
73  // lynxModels["FeatureTouch HSM Hi-Speed"] = "FB";
74 
75  // FE is deprecated, future firmwares will automatically switch to generic device type FD
76  lynxModels["FeatherTouch Motor PDMS"] = "FE";
77 
78  lynxModels["FeatherTouch Microtouch MSM Hi-Speed"] = "SO";
79  lynxModels["FeatherTouch Microtouch MSM Hi-Torque"] = "SP";
80  lynxModels["Starlight Instruments - FTM with MicroTouch"] = "SQ";
81 
82  //TA is deprecated, future firmwares will automatically switch to generic device type FA
83  lynxModels["Televue Focuser"] = "TA";
84 
85  lynxModels["Unipolar motor (Robo-Focus)"] = "RA";
86 
87  ModelS = nullptr;
88 
89  focusMoveRequest = 0;
90  simPosition = 0;
91 
92  // Can move in Absolute & Relative motions, can AbortFocuser motion, can sync, and has variable speed.
99 
100  canHome = false;
101  isHoming = false;
102 
103  simStatus[STATUS_MOVING] = ISS_OFF;
104  simStatus[STATUS_HOMING] = ISS_OFF;
105  simStatus[STATUS_HOMED] = ISS_OFF;
106  simStatus[STATUS_FFDETECT] = ISS_OFF;
107  simStatus[STATUS_TMPPROBE] = ISS_ON;
108  simStatus[STATUS_REMOTEIO] = ISS_ON;
109  simStatus[STATUS_HNDCTRL] = ISS_ON;
110  simStatus[STATUS_REVERSE] = ISS_OFF;
111 }
112 
113 /************************************************************************************
114  *
115 * ***********************************************************************************/
117 {
119 
120  // Focuser temperature
121  IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Celsius", "%6.2f", -50, 70., 0., 0.);
122  IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature",
124 
125  // Enable/Disable temperature compensation
126  IUFillSwitch(&TemperatureCompensateS[INDI_ENABLED], "INDI_ENABLED", "Enabled", ISS_OFF);
127  IUFillSwitch(&TemperatureCompensateS[INDI_DISABLED], "INDI_DISABLED", "Disabled", ISS_ON);
128  IUFillSwitchVector(&TemperatureCompensateSP, TemperatureCompensateS, 2, getDeviceName(), "T. COMPENSATION",
129  "T. Compensation",
131 
132  // Enable/Disable temperature compensation on start
133  IUFillSwitch(&TemperatureCompensateOnStartS[0], "Enable", "Enable", ISS_OFF);
134  IUFillSwitch(&TemperatureCompensateOnStartS[1], "Disable", "Disable", ISS_ON);
135  IUFillSwitchVector(&TemperatureCompensateOnStartSP, TemperatureCompensateOnStartS, 2, getDeviceName(),
136  "T. COMPENSATION @START", "T. Compensation @Start", FOCUS_SETTINGS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
137 
138  // Enable/Disable temperature Mode
139  IUFillSwitch(&TemperatureCompensateModeS[0], "A", "A", ISS_OFF);
140  IUFillSwitch(&TemperatureCompensateModeS[1], "B", "B", ISS_OFF);
141  IUFillSwitch(&TemperatureCompensateModeS[2], "C", "C", ISS_OFF);
142  IUFillSwitch(&TemperatureCompensateModeS[3], "D", "D", ISS_OFF);
143  IUFillSwitch(&TemperatureCompensateModeS[4], "E", "E", ISS_OFF);
144  IUFillSwitchVector(&TemperatureCompensateModeSP, TemperatureCompensateModeS, 5, getDeviceName(), "COMPENSATE MODE",
145  "Compensate Mode", FOCUS_SETTINGS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
146 
147  IUFillNumber(&TemperatureParamN[0], "T. Coefficient", "", "%.f", -9999, 9999, 100., 0.);
148  IUFillNumber(&TemperatureParamN[1], "T. Intercept", "", "%.f", -32766, 32766, 100., 0.);
149  IUFillNumberVector(&TemperatureParamNP, TemperatureParamN, 2, getDeviceName(), "T. PARAMETERS", "Mode Parameters",
151 
152  // Focuser Step Size
153  // An early command doc listed this as 10000 instead of the correct 1000. Because this is informational only (not used within the controller)
154  // fixing it should have no consequences.
155  IUFillNumber(&StepSizeN[0], "1000*microns/step", "", "%.f", 0, 65535, 0., 0);
156  IUFillNumberVector(&StepSizeNP, StepSizeN, 1, getDeviceName(), "STEP SIZE", "Step Size", FOCUS_SETTINGS_TAB, IP_RW, 0,
157  IPS_IDLE);
158 
159  // Reset to Factory setting
160  IUFillSwitch(&ResetS[0], "Factory", "Factory", ISS_OFF);
161  IUFillSwitchVector(&ResetSP, ResetS, 1, getDeviceName(), "RESET", "Reset", FOCUS_SETTINGS_TAB, IP_RW, ISR_ATMOST1, 0,
162  IPS_IDLE);
163 
164  // Go to home/center
165  IUFillSwitch(&GotoS[GOTO_CENTER], "Center", "Center", ISS_OFF);
166  IUFillSwitch(&GotoS[GOTO_HOME], "Home", "Home", ISS_OFF);
167  IUFillSwitchVector(&GotoSP, GotoS, 2, getDeviceName(), "GOTO", "Goto", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0,
168  IPS_IDLE);
169 
170  // List all supported models
171  std::map<std::string, std::string>::iterator iter;
172  int nModels = 1;
173  ModelS = static_cast<ISwitch *>(malloc(sizeof(ISwitch)));
174  // Need to be able to select no focuser to avoid troubles with Ekos
175  IUFillSwitch(ModelS, "No Focuser", "No Focuser", ISS_ON);
176  for (iter = lynxModels.begin(); iter != lynxModels.end(); ++iter)
177  {
178  ISwitch * buffer = static_cast<ISwitch *>(realloc(ModelS, (nModels + 1) * sizeof(ISwitch)));
179  if (!buffer)
180  {
181  free(ModelS);
182  return false;
183  }
184  else
185  ModelS = buffer;
186  IUFillSwitch(ModelS + nModels, (iter->first).c_str(), (iter->first).c_str(), ISS_OFF);
187 
188  nModels++;
189  }
190  IUFillSwitchVector(&ModelSP, ModelS, nModels, getDeviceName(), "MODEL", "Model", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0,
191  IPS_IDLE);
192 
193  // Status indicators
194  IUFillLight(&StatusL[STATUS_MOVING], "Is Moving", "", IPS_IDLE);
195  IUFillLight(&StatusL[STATUS_HOMING], "Is Homing", "", IPS_IDLE);
196  IUFillLight(&StatusL[STATUS_HOMED], "Is Homed", "", IPS_IDLE);
197  IUFillLight(&StatusL[STATUS_FFDETECT], "FF Detect", "", IPS_IDLE);
198  IUFillLight(&StatusL[STATUS_TMPPROBE], "Tmp Probe", "", IPS_IDLE);
199  IUFillLight(&StatusL[STATUS_REMOTEIO], "Remote IO", "", IPS_IDLE);
200  IUFillLight(&StatusL[STATUS_HNDCTRL], "Hnd Ctrl", "", IPS_IDLE);
201  IUFillLight(&StatusL[STATUS_REVERSE], "Reverse", "", IPS_IDLE);
202  IUFillLightVector(&StatusLP, StatusL, 8, getDeviceName(), "STATUS", "Status", FOCUS_STATUS_TAB, IPS_IDLE);
203 
204  // Focus name configure in the HUB
205  IUFillText(&HFocusNameT[0], "FocusName", "Focuser name", "");
206  IUFillTextVector(&HFocusNameTP, HFocusNameT, 1, getDeviceName(), "FOCUSNAME", "Focuser", FOCUS_SETTINGS_TAB, IP_RW, 0,
207  IPS_IDLE);
208 
209  // Led intensity value
210  IUFillNumber(&LedN[0], "Intensity", "", "%.f", 0, 100, 5., 0.);
212  //simPosition = FocusAbsPosN[0].value;
213 
214  addAuxControls();
215 
216  return true;
217 }
218 
219 /************************************************************************************
220  *
221 * ***********************************************************************************/
222 void FocusLynxBase::ISGetProperties(const char *dev)
223 {
224  if (dev != nullptr && strcmp(dev, getDeviceName()) != 0)
225  return;
226 
228 
230  if (isSimulation())
231  loadConfig(true, "Model");
232 }
233 
234 /************************************************************************************
235  *
236 * ***********************************************************************************/
238 {
239  // For homing focusers the vector is set to RO, as we get value from the HUB
240 
241  if(canHome)
242  {
244  }
245  else
246  {
248  }
249 
251 
252  if (isConnected())
253  {
254  defineProperty(&HFocusNameTP);
255 
256  defineProperty(&TemperatureNP);
257  defineProperty(&TemperatureCompensateModeSP);
258  defineProperty(&TemperatureParamNP);
259  defineProperty(&TemperatureCompensateSP);
260  defineProperty(&TemperatureCompensateOnStartSP);
261 
262  // defineProperty(&FocusBacklashSP);
263  // defineProperty(&FocusBacklashNP);
264 
265  //defineProperty(&MaxTravelNP);
266 
267  defineProperty(&StepSizeNP);
268 
269  defineProperty(&ResetSP);
270  //defineProperty(&ReverseSP);
271  defineProperty(&StatusLP);
272 
273  if (getFocusConfig() && getFocusTemp())
274  LOG_INFO("FocusLynx parameters updated, focuser ready for use.");
275  else
276  {
277  LOG_ERROR("Failed to retrieve focuser configuration settings...");
278  return false;
279  }
280  }
281  else
282  {
283  deleteProperty(TemperatureNP.name);
284  deleteProperty(TemperatureCompensateModeSP.name);
285  deleteProperty(TemperatureCompensateSP.name);
286  deleteProperty(TemperatureParamNP.name);
287  deleteProperty(TemperatureCompensateOnStartSP.name);
288 
289  // deleteProperty(FocusBacklashSP.name);
290  // deleteProperty(FocusBacklashNP.name);
291 
292  //deleteProperty(MaxTravelNP.name);
293  deleteProperty(StepSizeNP.name);
294 
295  deleteProperty(ResetSP.name);
296  deleteProperty(GotoSP.name);
297  //deleteProperty(ReverseSP.name);
298 
299  deleteProperty(StatusLP.name);
300  deleteProperty(HFocusNameTP.name);
301  }
302 
303  return true;
304 }
305 
306 /************************************************************************************
307  *
308 * ***********************************************************************************/
310 {
311  if (ack())
312  {
313  LOG_INFO("FocusLynx is online. Getting focus parameters...");
314  return true;
315  }
316 
317  LOG_INFO("Error retrieving data from FocusLynx, please ensure FocusLynxBase controller is "
318  "powered and the port is correct.");
319  return false;
320 }
321 
322 /************************************************************************************
323  *
324 * ***********************************************************************************/
326 {
327  // Has to be overide by child instance
328  return "FocusLynxBase";
329 }
330 
331 /************************************************************************************
332  *
333 * ***********************************************************************************/
334 bool FocusLynxBase::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
335 {
336  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
337  {
338  // Models
339  if (strcmp(ModelSP.name, name) == 0)
340  {
341  IUUpdateSwitch(&ModelSP, states, names, n);
342  ModelSP.s = IPS_OK;
343  IDSetSwitch(&ModelSP, nullptr);
344  if (isConnected())
345  {
347  LOG_INFO("Focuser model set. Please disconnect and reconnect now...");
348  }
349  else
350  LOG_INFO("Focuser model set. Please connect now...");
351 
352  //Read the config for this new model form the HUB
353  getFocusConfig();
354 
355  return true;
356  }
357 
358  // Temperature Compensation
359  if (strcmp(TemperatureCompensateSP.name, name) == 0)
360  {
361  int prevIndex = IUFindOnSwitchIndex(&TemperatureCompensateSP);
362  IUUpdateSwitch(&TemperatureCompensateSP, states, names, n);
363  if (setTemperatureCompensation(TemperatureCompensateS[0].s == ISS_ON))
364  {
365  TemperatureCompensateSP.s = IPS_OK;
366  }
367  else
368  {
369  IUResetSwitch(&TemperatureCompensateSP);
370  TemperatureCompensateSP.s = IPS_ALERT;
371  TemperatureCompensateS[prevIndex].s = ISS_ON;
372  }
373 
374  IDSetSwitch(&TemperatureCompensateSP, nullptr);
375  return true;
376  }
377 
378  // Temperature Compensation on Start
379  if (!strcmp(TemperatureCompensateOnStartSP.name, name))
380  {
381  int prevIndex = IUFindOnSwitchIndex(&TemperatureCompensateOnStartSP);
382  IUUpdateSwitch(&TemperatureCompensateOnStartSP, states, names, n);
383  if (setTemperatureCompensationOnStart(TemperatureCompensateOnStartS[0].s == ISS_ON))
384  {
385  TemperatureCompensateOnStartSP.s = IPS_OK;
386  }
387  else
388  {
389  IUResetSwitch(&TemperatureCompensateOnStartSP);
390  TemperatureCompensateOnStartSP.s = IPS_ALERT;
391  TemperatureCompensateOnStartS[prevIndex].s = ISS_ON;
392  }
393 
394  IDSetSwitch(&TemperatureCompensateOnStartSP, nullptr);
395  return true;
396  }
397 
398  // Temperature Compensation Mode
399  if (!strcmp(TemperatureCompensateModeSP.name, name))
400  {
401  int prevIndex = IUFindOnSwitchIndex(&TemperatureCompensateModeSP);
402  IUUpdateSwitch(&TemperatureCompensateModeSP, states, names, n);
403  char mode = IUFindOnSwitchIndex(&TemperatureCompensateModeSP) + 'A';
404  if (setTemperatureCompensationMode(mode))
405  {
406  TemperatureCompensateModeSP.s = IPS_OK;
407  }
408  else
409  {
410  IUResetSwitch(&TemperatureCompensateModeSP);
411  TemperatureCompensateModeSP.s = IPS_ALERT;
412  TemperatureCompensateModeS[prevIndex].s = ISS_ON;
413  }
414 
415  IDSetSwitch(&TemperatureCompensateModeSP, nullptr);
416  return true;
417  }
418 
419  // Backlash enable/disable
420  // if (!strcmp(FocusBacklashSP.name, name))
421  // {
422  // int prevIndex = IUFindOnSwitchIndex(&FocusBacklashSP);
423  // IUUpdateSwitch(&FocusBacklashSP, states, names, n);
424  // if (setBacklashCompensation(FocusBacklashS[INDI_ENABLED].s == ISS_ON))
425  // {
426  // FocusBacklashSP.s = IPS_OK;
427  // }
428  // else
429  // {
430  // IUResetSwitch(&FocusBacklashSP);
431  // FocusBacklashSP.s = IPS_ALERT;
432  // FocusBacklashS[prevIndex].s = ISS_ON;
433  // }
434 
435  // IDSetSwitch(&FocusBacklashSP, nullptr);
436  // return true;
437  // }
438 
439  // Reset to Factory setting
440  if (strcmp(ResetSP.name, name) == 0)
441  {
442  IUResetSwitch(&ResetSP);
443  if (resetFactory())
444  ResetSP.s = IPS_OK;
445  else
446  ResetSP.s = IPS_ALERT;
447 
448  IDSetSwitch(&ResetSP, nullptr);
449  return true;
450  }
451 
452  // Go to home/center
453  if (!strcmp(GotoSP.name, name))
454  {
455  IUUpdateSwitch(&GotoSP, states, names, n);
456 
457  if (GotoS[GOTO_HOME].s == ISS_ON)
458  {
459  if (home())
460  GotoSP.s = IPS_BUSY;
461  else
462  GotoSP.s = IPS_ALERT;
463  }
464  else
465  {
466  if (center())
467  GotoSP.s = IPS_BUSY;
468  else
469  GotoSP.s = IPS_ALERT;
470  }
471 
472  IDSetSwitch(&GotoSP, nullptr);
473  return true;
474  }
475 
476  // Reverse Direction
477  // if (!strcmp(ReverseSP.name, name))
478  // {
479  // IUUpdateSwitch(&ReverseSP, states, names, n);
480 
481  // if (reverse(ReverseS[0].s == ISS_ON))
482  // ReverseSP.s = IPS_OK;
483  // else
484  // ReverseSP.s = IPS_ALERT;
485 
486  // IDSetSwitch(&ReverseSP, nullptr);
487  // return true;
488  // }
489 
490  }
491  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
492 }
493 
494 /************************************************************************************
495  *
496 * ***********************************************************************************/
497 bool FocusLynxBase::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
498 {
499  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
500  {
501  // Set device nickname to the HUB itself
502  if (!strcmp(name, HFocusNameTP.name))
503  {
504  IUUpdateText(&HFocusNameTP, texts, names, n);
505  if (setDeviceNickname(HFocusNameT[0].text))
506  HFocusNameTP.s = IPS_OK;
507  else
508  HFocusNameTP.s = IPS_ALERT;
509  IDSetText(&HFocusNameTP, nullptr);
510  return true;
511  }
512  }
513  return INDI::Focuser::ISNewText(dev, name, texts, names, n);
514 }
515 
516 /************************************************************************************
517  *
518 * ***********************************************************************************/
519 bool FocusLynxBase::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
520 {
521  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
522  {
523  // Temperature Coefficient & Inceptions
524  if (!strcmp(TemperatureParamNP.name, name))
525  {
526  IUUpdateNumber(&TemperatureParamNP, values, names, n);
527 
528  char mode = static_cast<char>(65 + IUFindOnSwitchIndex(&TemperatureCompensateModeSP));
529  if (!setTemperatureCompensationCoeff(mode, TemperatureParamN[0].value) ||
530  !setTemperatureInceptions(mode, TemperatureParamN[1].value))
531  {
532  LOG_ERROR("Failed to write temperature coefficient or intercept");
533  TemperatureParamNP.s = IPS_ALERT;
534  IDSetNumber(&TemperatureParamNP, nullptr);
535  return false;
536  }
537 
538  TemperatureParamNP.s = IPS_OK;
539  getFocusTemp();
540 
541  return true;
542  }
543 
544  // Backlash Value
545  // if (!strcmp(FocusBacklashNP.name, name))
546  // {
547  // IUUpdateNumber(&FocusBacklashNP, values, names, n);
548  // if (setFocusBacklashSteps(FocusBacklashN[0].value) == false)
549  // {
550  // LOG_ERROR("Failed to set temperature coefficients.");
551  // FocusBacklashNP.s = IPS_ALERT;
552  // IDSetNumber(&FocusBacklashNP, nullptr);
553  // return false;
554  // }
555 
556  // FocusBacklashNP.s = IPS_OK;
557  // IDSetNumber(&FocusBacklashNP, nullptr);
558  // return true;
559  // }
560 
561  // Sync
562  // if (strcmp(SyncNP.name, name) == 0)
563  // {
564  // IUUpdateNumber(&SyncNP, values, names, n);
565  // if (sync(SyncN[0].value) == false)
566  // {
567  // LOG_ERROR("Failed to set the actual value.");
568  // SyncNP.s = IPS_ALERT;
569  // IDSetNumber(&SyncNP, nullptr);
570  // return false;
571  // }
572  // else
573  // SyncNP.s = IPS_OK;
574 
575  // IDSetNumber(&SyncNP, nullptr);
576  // return true;
577  // }
578 
579  // StepSize
580  if (strcmp(StepSizeNP.name, name) == 0)
581  {
582  IUUpdateNumber(&StepSizeNP, values, names, n);
583  if (setStepSize(StepSizeN[0].value) == false)
584  {
585  LOG_ERROR("Failed to set the actual value.");
586  StepSizeNP.s = IPS_ALERT;
587  IDSetNumber(&StepSizeNP, nullptr);
588  return false;
589  }
590  else
591  StepSizeNP.s = IPS_OK;
592 
593  IDSetNumber(&StepSizeNP, nullptr);
594  return true;
595  }
596 
597  // Max Travel if relative focusers
598  // if (strcmp(MaxTravelNP.name, name) == 0)
599  // {
600  // IUUpdateNumber(&MaxTravelNP, values, names, n);
601 
602  // if (setMaxTravel(MaxTravelN[0].value) == false)
603  // MaxTravelNP.s = IPS_ALERT;
604  // else
605  // {
606  // MaxTravelNP.s = IPS_OK;
607  // FocusAbsPosN[0].max = SyncN[0].max = MaxTravelN[0].value;
608  // FocusAbsPosN[0].step = SyncN[0].step = (MaxTravelN[0].value / 50.0);
609 
610  // IUUpdateMinMax(&FocusAbsPosNP);
611  // IUUpdateMinMax(&SyncNP);
612 
613  // IDSetNumber(&MaxTravelNP, nullptr);
614 
615  // LOGF_INFO("Focuser absolute limits: min (%g) max (%g)", FocusAbsPosN[0].min,
616  // FocusAbsPosN[0].max);
617  // }
618  // return true;
619  // }
620 
621  // Set LED intensity to the HUB itself via function setLedLevel()
622  if (!strcmp(LedNP.name, name))
623  {
624  IUUpdateNumber(&LedNP, values, names, n);
625  if (setLedLevel(LedN[0].value))
626  LedNP.s = IPS_OK;
627  else
628  LedNP.s = IPS_ALERT;
629  LOGF_INFO("Focuser LED level intensity : %f", LedN[0].value);
630  IDSetNumber(&LedNP, nullptr);
631  return true;
632  }
633  }
634 
635  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
636 }
637 
638 /************************************************************************************
639  *
640 * ***********************************************************************************/
642 {
643  char cmd[LYNX_MAX] = {0};
644  int errcode = 0;
645  char errmsg[MAXRBUF];
646  char response[LYNX_MAX] = {0};
647  int nbytes_read = 0;
648  int nbytes_written = 0;
649 
650  memset(response, 0, sizeof(response));
651 
652  snprintf(cmd, LYNX_MAX, "<%sHELLO>", getFocusTarget());
653  LOGF_DEBUG("CMD (%s)", cmd);
654 
655  if (isSimulation())
656  {
657  const char *focusName = IUFindOnSwitch(&ModelSP)->label;
658  strncpy(response, focusName, LYNX_MAX);
659  nbytes_read = strlen(response) + 1;
660  }
661  else
662  {
663  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
664  {
665  tty_error_msg(errcode, errmsg, MAXRBUF);
666  LOGF_ERROR("%s", errmsg);
667  return false;
668  }
669 
670  if (!isResponseOK())
671  return false;
672 
673  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
674  {
675  tty_error_msg(errcode, errmsg, MAXRBUF);
676  LOGF_ERROR("%s", errmsg);
677  return false;
678  }
679  }
680 
681  if (nbytes_read > 0)
682  {
683  response[nbytes_read - 1] = '\0';
684  LOGF_DEBUG("RES (%s)", response);
685  LOGF_INFO("%s is detected.", response);
686 
687  return true;
688  }
689 
690  return false;
691 }
692 
693 /************************************************************************************
694  *
695 * ***********************************************************************************/
696 bool FocusLynxBase::getFocusConfig()
697 {
698  char cmd[LYNX_MAX] = {0};
699  int errcode = 0;
700  char errmsg[MAXRBUF];
701  char response[LYNX_MAX] = {0};
702  int nbytes_read = 0;
703  int nbytes_written = 0;
704  char key[16];
705 
706  memset(response, 0, sizeof(response));
707 
708  snprintf(cmd, LYNX_MAX, "<%sGETCONFIG>", getFocusTarget());
709  LOGF_DEBUG("CMD (%s)", cmd);
710 
711  if (isSimulation())
712  {
713  if (!strcmp(getFocusTarget(), "F1"))
714  strncpy(response, "CONFIG1", 16);
715  else
716  strncpy(response, "CONFIG2", 16);
717  nbytes_read = strlen(response) + 1;
718  }
719  else
720  {
721  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
722  {
723  tty_error_msg(errcode, errmsg, MAXRBUF);
724  LOGF_ERROR("%s", errmsg);
725  return false;
726  }
727 
728  if (!isResponseOK())
729  return false;
730 
731  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
732  {
733  tty_error_msg(errcode, errmsg, MAXRBUF);
734  LOGF_ERROR("%s", errmsg);
735  return false;
736  }
737  }
738 
739  if (nbytes_read > 0)
740  {
741  response[nbytes_read - 1] = '\0';
742  LOGF_DEBUG("RES (%s)", response);
743 
744  if ((strcmp(response, "CONFIG1")) && (strcmp(response, "CONFIG2")))
745  return false;
746  }
747 
748  memset(response, 0, sizeof(response));
749 
750  // Nickname
751  if (isSimulation())
752  {
753  snprintf(response, sizeof(response), "NickName=Focuser#%s\n", getFocusTarget());
754  nbytes_read = strlen(response);
755  }
756  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
757  {
758  tty_error_msg(errcode, errmsg, MAXRBUF);
759  LOGF_ERROR("%s", errmsg);
760  return false;
761  }
762  response[nbytes_read - 1] = '\0';
763  LOGF_DEBUG("RES (%s)", response);
764 
765  char nickname[16];
766  int rc = sscanf(response, "%16[^=]=%16[^\n]s", key, nickname);
767 
768  if (rc != 2)
769  return false;
770 
771  IUSaveText(&HFocusNameT[0], nickname);
772  IDSetText(&HFocusNameTP, nullptr);
773 
774  HFocusNameTP.s = IPS_OK;
775  IDSetText(&HFocusNameTP, nullptr);
776 
777  memset(response, 0, sizeof(response));
778 
779  // Get Max Position
780  if (isSimulation())
781  {
782  // Default value from non-homing focusers
783  snprintf(response, 32, "Max Pos = %06d\n", 65535);
784  nbytes_read = strlen(response);
785  }
786  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
787  {
788  tty_error_msg(errcode, errmsg, MAXRBUF);
789  LOGF_ERROR("%s", errmsg);
790  return false;
791  }
792  response[nbytes_read - 1] = '\0';
793  LOGF_DEBUG("RES (%s)", response);
794 
795  uint32_t maxPos = 0;
796  rc = sscanf(response, "%16[^=]=%d", key, &maxPos);
797  if (rc == 2)
798  {
799  FocusAbsPosN[0].min = 0;
800  FocusAbsPosN[0].max = maxPos;
801  FocusAbsPosN[0].step = maxPos / 50.0;
802 
803  FocusSyncN[0].min = 0;
804  FocusSyncN[0].max = maxPos;
805  FocusSyncN[0].step = maxPos / 50.0;
806 
807  FocusRelPosN[0].min = 0;
808  FocusRelPosN[0].max = maxPos / 2;
809  FocusRelPosN[0].step = maxPos / 100.0;
810 
814 
816  FocusMaxPosN[0].value = maxPos;
817  IDSetNumber(&FocusMaxPosNP, nullptr);
818 
819  }
820  else
821  return false;
822 
823  memset(response, 0, sizeof(response));
824 
825  // Get Device Type
826  if (isSimulation())
827  {
828  // In simulation each focuser is different, one Absolute and one relative
829  if (strcmp(getFocusTarget(), "F2"))
830  snprintf(response, 32, "Dev Type = %s\n", "OA");
831  else
832  snprintf(response, 32, "Dev Type = %s\n", "SO");
833  nbytes_read = strlen(response);
834  }
835  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
836  {
837  tty_error_msg(errcode, errmsg, MAXRBUF);
838  LOGF_ERROR("%s", errmsg);
839  return false;
840  }
841  response[nbytes_read - 1] = '\0';
842  LOGF_DEBUG("RES (%s)", response);
843 
844  // Don't process the response if isSimulation active, Value read from saved config
845  if (!isSimulation())
846  {
847  //Extract the code from the response value
848  std::string tmpString;
849  tmpString.assign(response + 11, 2);
850  int count = 0;
851 
852  //As "ZZ" is not exist in lynxModel, not need interator, 'No focuser' is known as first in ModelS
853  if(tmpString != "ZZ")
854  {
855  //Reset the Home / Center function
856  deleteProperty(GotoSP.name);
857  //All models that can home have the first character of the device type as the letter 'O'
858  canHome = tmpString[0] == 'O';
859 
860  if(canHome)
861  {
862  //Homing focusers can not sync
864  GotoSP.nsp = 2;
865  }
866  else
867  {
868  //Non-Homing focusers can sync
870  GotoSP.nsp = 1;
871  }
872 
873  //Reactivate the Home / Center Property
874  defineProperty(&GotoSP);
875 
876  // If not 'No Focuser' then do iterator
877  // iterate throught all elements in std::map<std::string, std::string> and search the index from the code.
878  std::map<std::string, std::string>::iterator it = lynxModels.begin();
879  while(it != lynxModels.end())
880  {
881  count++;
882  if (it->second == tmpString)
883  break;
884  it++;
885  }
886  }
887 
888  // as different focuser could have the same code in the HUB, we are not able to find the correct name in the list of focuser.
889  // The first one would be show as the item.
891  ModelS[count].s = ISS_ON;
892  IDSetSwitch(&ModelSP, nullptr);
893 
894  LOGF_DEBUG("Index focuser : %d", count);
895  } // end if (!isSimulation)
896 
897  // Get Status Parameters
898 
899  memset(response, 0, sizeof(response));
900 
901  // Temperature information processed on function getFocusTemp(), do nothing with related response
902 
903  // Temperature Compensation On
904  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
905  {
906  tty_error_msg(errcode, errmsg, MAXRBUF);
907  LOGF_ERROR("%s", errmsg);
908  return false;
909  }
910 
911  // Temperature Coeff A
912  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
913  {
914  tty_error_msg(errcode, errmsg, MAXRBUF);
915  LOGF_ERROR("%s", errmsg);
916  return false;
917  }
918 
919  // Temperature Coeff B
920  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
921  {
922  tty_error_msg(errcode, errmsg, MAXRBUF);
923  LOGF_ERROR("%s", errmsg);
924  return false;
925  }
926 
927  // Temperature Coeff C
928  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
929  {
930  tty_error_msg(errcode, errmsg, MAXRBUF);
931  LOGF_ERROR("%s", errmsg);
932  return false;
933  }
934 
935  // Temperature Coeff D
936  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
937  {
938  tty_error_msg(errcode, errmsg, MAXRBUF);
939  LOGF_ERROR("%s", errmsg);
940  return false;
941  }
942 
943  // Temperature Coeff E
944  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
945  {
946  tty_error_msg(errcode, errmsg, MAXRBUF);
947  LOGF_ERROR("%s", errmsg);
948  return false;
949  }
950 
951  // Temperature Compensation Mode
952  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
953  {
954  tty_error_msg(errcode, errmsg, MAXRBUF);
955  LOGF_ERROR("%s", errmsg);
956  return false;
957  }
958 
959  // Backlash Compensation
960  if (isSimulation())
961  {
962  snprintf(response, 32, "BLC En = %d\n", FocusBacklashS[INDI_ENABLED].s == ISS_ON ? 1 : 0);
963  nbytes_read = strlen(response);
964  }
965  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
966  {
967  tty_error_msg(errcode, errmsg, MAXRBUF);
968  LOGF_ERROR("%s", errmsg);
969  return false;
970  }
971  response[nbytes_read - 1] = '\0';
972  LOGF_DEBUG("RES (%s)", response);
973 
974  int BLCCompensate;
975  rc = sscanf(response, "%16[^=]=%d", key, &BLCCompensate);
976  if (rc != 2)
977  return false;
978 
980  FocusBacklashS[INDI_ENABLED].s = BLCCompensate ? ISS_ON : ISS_OFF;
981  FocusBacklashS[INDI_DISABLED].s = BLCCompensate ? ISS_OFF : ISS_ON;
983  IDSetSwitch(&FocusBacklashSP, nullptr);
984 
985  // Backlash Value
986  memset(response, 0, sizeof(response));
987  if (isSimulation())
988  {
989  snprintf(response, 32, "BLC Stps = %d\n", 50);
990  nbytes_read = strlen(response);
991  }
992  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
993  {
994  tty_error_msg(errcode, errmsg, MAXRBUF);
995  LOGF_ERROR("%s", errmsg);
996  return false;
997  }
998  response[nbytes_read - 1] = '\0';
999  LOGF_DEBUG("RES (%s)", response);
1000 
1001  int BLCValue;
1002  rc = sscanf(response, "%16[^=]=%d", key, &BLCValue);
1003  if (rc != 2)
1004  return false;
1005 
1006  FocusBacklashN[0].value = BLCValue;
1008  IDSetNumber(&FocusBacklashNP, nullptr);
1009 
1010  // Led brightnesss
1011  memset(response, 0, sizeof(response));
1012  if (isSimulation())
1013  {
1014  snprintf(response, 32, "LED Brt = %d\n", 75);
1015  nbytes_read = strlen(response);
1016  }
1017  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1018  {
1019  tty_error_msg(errcode, errmsg, MAXRBUF);
1020  LOGF_ERROR("%s", errmsg);
1021  return false;
1022  }
1023  response[nbytes_read - 1] = '\0';
1024  LOGF_DEBUG("RES (%s)", response);
1025 
1026  int LEDBrightness;
1027  rc = sscanf(response, "%16[^=]=%d", key, &LEDBrightness);
1028  if (rc != 2)
1029  return false;
1030 
1031  LedN[0].value = LEDBrightness;
1032  LedNP.s = IPS_OK;
1033  IDSetNumber(&LedNP, nullptr);
1034 
1035  // Temperature Compensation on Start
1036  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1037  {
1038  tty_error_msg(errcode, errmsg, MAXRBUF);
1039  LOGF_ERROR("%s", errmsg);
1040  return false;
1041  }
1042 
1043  // Home on start?
1044  // JM 2021.05.09: This appears to be a new addition in firmware v1.2.0 (2019).
1045  // We should ignore if END is received instead.
1046  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1047  {
1048  tty_error_msg(errcode, errmsg, MAXRBUF);
1049  LOGF_ERROR("%s", errmsg);
1050  return false;
1051  }
1052  // If END, then ignore
1053  else if (strncmp(response, "END", 3))
1054  {
1055  int homeOnStart;
1056  rc = sscanf(response, "%16[^=]=%d", key, &homeOnStart);
1057  if (rc != 2)
1058  return false;
1059 
1060  m_HomeOnStart = homeOnStart == 1;
1061  }
1062 
1063  // If last response was END, then ignore
1064  if (strncmp(response, "END", 3))
1065  {
1066  // END is reached
1067  memset(response, 0, sizeof(response));
1068  if (isSimulation())
1069  {
1070  strncpy(response, "END\n", 16);
1071  nbytes_read = strlen(response);
1072  }
1073  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1074  {
1075  tty_error_msg(errcode, errmsg, MAXRBUF);
1076  LOGF_ERROR("%s", errmsg);
1077  return false;
1078  }
1079  }
1080 
1081  if (nbytes_read > 0)
1082  {
1083  response[nbytes_read - 1] = '\0';
1084 
1085  // Display the response to be sure to have read the complet TTY Buffer.
1086  LOGF_DEBUG("RES (%s)", response);
1087 
1088  if (strcmp(response, "END"))
1089  return false;
1090  }
1091 
1092  tcflush(PortFD, TCIFLUSH);
1093 
1094  configurationComplete = true;
1095 
1096  return true;
1097 }
1098 
1099 /************************************************************************************
1100  *
1101 * ***********************************************************************************/
1102 bool FocusLynxBase::getFocusStatus()
1103 {
1104  char cmd[LYNX_MAX] = {0};
1105  int errcode = 0;
1106  char errmsg[MAXRBUF];
1107  char response[LYNX_MAX] = {0};
1108  int nbytes_read = 0;
1109  int nbytes_written = 0;
1110  char key[16];
1111 
1112  memset(response, 0, sizeof(response));
1113 
1114  snprintf(cmd, LYNX_MAX, "<%sGETSTATUS>", getFocusTarget());
1115  LOGF_DEBUG("CMD (%s)", cmd);
1116 
1117  if (isSimulation())
1118  {
1119  if (!strcmp(getFocusTarget(), "F1"))
1120  strncpy(response, "STATUS1", 16);
1121  else
1122  strncpy(response, "STATUS2", 16);
1123  nbytes_read = strlen(response) + 1;
1124  }
1125  else
1126  {
1127  //tcflush(PortFD, TCIFLUSH);
1128 
1129  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1130  {
1131  tty_error_msg(errcode, errmsg, MAXRBUF);
1132  LOGF_ERROR("%s", errmsg);
1133  return false;
1134  }
1135 
1136  if (!isResponseOK())
1137  return false;
1138 
1139  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1140  {
1141  tty_error_msg(errcode, errmsg, MAXRBUF);
1142  LOGF_ERROR("%s", errmsg);
1143  return false;
1144  }
1145  }
1146 
1147  if (nbytes_read > 0)
1148  {
1149  response[nbytes_read - 1] = '\0';
1150  LOGF_DEBUG("RES (%s)", response);
1151 
1152  if (!((!strcmp(response, "STATUS1")) && (!strcmp(getFocusTarget(), "F1"))) && !((!strcmp(response, "STATUS2"))
1153  && (!strcmp(getFocusTarget(), "F2"))))
1154  {
1155  tcflush(PortFD, TCIFLUSH);
1156  return false;
1157  }
1158 
1159  // Get Temperature
1160  memset(response, 0, sizeof(response));
1161  if (isSimulation())
1162  {
1163  //strncpy(response, "Temp(C) = +21.7\n", 16); // #PS: for string literal, use strcpy
1164  strcpy(response, "Temp(C) = +21.7\n");
1165  nbytes_read = strlen(response);
1166  }
1167  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1168  {
1169  tty_error_msg(errcode, errmsg, MAXRBUF);
1170  LOGF_ERROR("%s", errmsg);
1171  return false;
1172  }
1173 
1174  if (nbytes_read > 0)
1175  response[nbytes_read - 1] = '\0'; // remove last character (new line)
1176 
1177  LOGF_DEBUG("RES (%s)", response);
1178 
1179  float temperature = 0;
1180  int rc = sscanf(response, "%16[^=]=%f", key, &temperature);
1181  if (rc == 2)
1182  {
1183  TemperatureN[0].value = temperature;
1184  IDSetNumber(&TemperatureNP, nullptr);
1185  }
1186  else
1187  {
1188  if (TemperatureNP.s != IPS_ALERT)
1189  {
1190  TemperatureNP.s = IPS_ALERT;
1191  IDSetNumber(&TemperatureNP, nullptr);
1192  }
1193  }
1194 
1195  // Get Current Position
1196  memset(response, 0, sizeof(response));
1197  if (isSimulation())
1198  {
1199  snprintf(response, 32, "Curr Pos = %06d\n", simPosition);
1200  nbytes_read = strlen(response);
1201  }
1202  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1203  {
1204  tty_error_msg(errcode, errmsg, MAXRBUF);
1205  LOGF_ERROR("%s", errmsg);
1206  return false;
1207  }
1208  response[nbytes_read - 1] = '\0';
1209  LOGF_DEBUG("RES (%s)", response);
1210 
1211  uint32_t currPos = 0;
1212  rc = sscanf(response, "%16[^=]=%d", key, &currPos);
1213  if (rc == 2)
1214  {
1215  FocusAbsPosN[0].value = currPos;
1216  IDSetNumber(&FocusAbsPosNP, nullptr);
1217  }
1218  else
1219  return false;
1220 
1221  // Get Target Position
1222  memset(response, 0, sizeof(response));
1223  if (isSimulation())
1224  {
1225  snprintf(response, 32, "Targ Pos = %06d\n", targetPosition);
1226  nbytes_read = strlen(response);
1227  }
1228  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1229  {
1230  tty_error_msg(errcode, errmsg, MAXRBUF);
1231  LOGF_ERROR("%s", errmsg);
1232  return false;
1233  }
1234  response[nbytes_read - 1] = '\0';
1235  LOGF_DEBUG("RES (%s)", response);
1236 
1237  // Get Status Parameters
1238 
1239  // #1 is Moving?
1240  memset(response, 0, sizeof(response));
1241  if (isSimulation())
1242  {
1243  snprintf(response, 32, "Is Moving = %d\n", (simStatus[STATUS_MOVING] == ISS_ON) ? 1 : 0);
1244  nbytes_read = strlen(response);
1245  }
1246  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1247  {
1248  tty_error_msg(errcode, errmsg, MAXRBUF);
1249  LOGF_ERROR("%s", errmsg);
1250  return false;
1251  }
1252  response[nbytes_read - 1] = '\0';
1253  LOGF_DEBUG("RES (%s)", response);
1254 
1255  int isMoving;
1256  rc = sscanf(response, "%16[^=]=%d", key, &isMoving);
1257  if (rc != 2)
1258  return false;
1259 
1260  StatusL[STATUS_MOVING].s = isMoving ? IPS_BUSY : IPS_IDLE;
1261 
1262  // #2 is Homing?
1263  memset(response, 0, sizeof(response));
1264  if (isSimulation())
1265  {
1266  snprintf(response, 32, "Is Homing = %d\n", (simStatus[STATUS_HOMING] == ISS_ON) ? 1 : 0);
1267  nbytes_read = strlen(response);
1268  }
1269  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1270  {
1271  tty_error_msg(errcode, errmsg, MAXRBUF);
1272  LOGF_ERROR("%s", errmsg);
1273  return false;
1274  }
1275  response[nbytes_read - 1] = '\0';
1276  LOGF_DEBUG("RES (%s)", response);
1277 
1278  int _isHoming;
1279  rc = sscanf(response, "%16[^=]=%d", key, &_isHoming);
1280  if (rc != 2)
1281  return false;
1282 
1283  StatusL[STATUS_HOMING].s = _isHoming ? IPS_BUSY : IPS_IDLE;
1284  // For syncing only focusers home is not applicable.
1285  if (canHome == false)
1286  StatusL[STATUS_HOMING].s = IPS_IDLE;
1287 
1288  // We set that isHoming in process, but we don't set it to false here it must be reset in TimerHit
1289  if (StatusL[STATUS_HOMING].s == IPS_BUSY)
1290  isHoming = true;
1291 
1292  // #3 is Homed?
1293  memset(response, 0, sizeof(response));
1294  if (isSimulation())
1295  {
1296  snprintf(response, 32, "Is Homed = %d\n", (simStatus[STATUS_HOMED] == ISS_ON) ? 1 : 0);
1297  nbytes_read = strlen(response);
1298  }
1299  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1300  {
1301  tty_error_msg(errcode, errmsg, MAXRBUF);
1302  LOGF_ERROR("%s", errmsg);
1303  return false;
1304  }
1305  response[nbytes_read - 1] = '\0';
1306  LOGF_DEBUG("RES (%s)", response);
1307 
1308  int isHomed;
1309  rc = sscanf(response, "%16[^=]=%d", key, &isHomed);
1310  if (rc != 2)
1311  return false;
1312 
1313  StatusL[STATUS_HOMED].s = isHomed ? IPS_OK : IPS_IDLE;
1314  // For relative focusers home is not applicable.
1315  if (canHome == false)
1316  StatusL[STATUS_HOMED].s = IPS_IDLE;
1317 
1318  // #4 FF Detected?
1319  memset(response, 0, sizeof(response));
1320  if (isSimulation())
1321  {
1322  snprintf(response, 32, "FFDetect = %d\n", (simStatus[STATUS_FFDETECT] == ISS_ON) ? 1 : 0);
1323  nbytes_read = strlen(response);
1324  }
1325  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1326  {
1327  tty_error_msg(errcode, errmsg, MAXRBUF);
1328  LOGF_ERROR("%s", errmsg);
1329  return false;
1330  }
1331  response[nbytes_read - 1] = '\0';
1332  LOGF_DEBUG("RES (%s)", response);
1333 
1334  int FFDetect;
1335  rc = sscanf(response, "%16[^=]=%d", key, &FFDetect);
1336  if (rc != 2)
1337  return false;
1338 
1339  StatusL[STATUS_FFDETECT].s = FFDetect ? IPS_OK : IPS_IDLE;
1340 
1341  // #5 Temperature probe?
1342  memset(response, 0, sizeof(response));
1343  if (isSimulation())
1344  {
1345  snprintf(response, 32, "TmpProbe = %d\n", (simStatus[STATUS_TMPPROBE] == ISS_ON) ? 1 : 0);
1346  nbytes_read = strlen(response);
1347  }
1348  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1349  {
1350  tty_error_msg(errcode, errmsg, MAXRBUF);
1351  LOGF_ERROR("%s", errmsg);
1352  return false;
1353  }
1354  response[nbytes_read - 1] = '\0';
1355  LOGF_DEBUG("RES (%s)", response);
1356 
1357  int TmpProbe;
1358  rc = sscanf(response, "%16[^=]=%d", key, &TmpProbe);
1359  if (rc != 2)
1360  return false;
1361 
1362  StatusL[STATUS_TMPPROBE].s = TmpProbe ? IPS_OK : IPS_IDLE;
1363 
1364  // #6 Remote IO?
1365  memset(response, 0, sizeof(response));
1366  if (isSimulation())
1367  {
1368  snprintf(response, 32, "RemoteIO = %d\n", (simStatus[STATUS_REMOTEIO] == ISS_ON) ? 1 : 0);
1369  nbytes_read = strlen(response);
1370  }
1371  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1372  {
1373  tty_error_msg(errcode, errmsg, MAXRBUF);
1374  LOGF_ERROR("%s", errmsg);
1375  return false;
1376  }
1377  response[nbytes_read - 1] = '\0';
1378  LOGF_DEBUG("RES (%s)", response);
1379 
1380  int RemoteIO;
1381  rc = sscanf(response, "%16[^=]=%d", key, &RemoteIO);
1382  if (rc != 2)
1383  return false;
1384 
1385  StatusL[STATUS_REMOTEIO].s = RemoteIO ? IPS_OK : IPS_IDLE;
1386 
1387  // #7 Hand controller?
1388  memset(response, 0, sizeof(response));
1389  if (isSimulation())
1390  {
1391  snprintf(response, 32, "Hnd Ctlr = %d\n", (simStatus[STATUS_HNDCTRL] == ISS_ON) ? 1 : 0);
1392  nbytes_read = strlen(response);
1393  }
1394  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1395  {
1396  tty_error_msg(errcode, errmsg, MAXRBUF);
1397  LOGF_ERROR("%s", errmsg);
1398  return false;
1399  }
1400  response[nbytes_read - 1] = '\0';
1401  LOGF_DEBUG("RES (%s)", response);
1402 
1403  int HndCtlr;
1404  rc = sscanf(response, "%16[^=]=%d", key, &HndCtlr);
1405  if (rc != 2)
1406  return false;
1407 
1408  StatusL[STATUS_HNDCTRL].s = HndCtlr ? IPS_OK : IPS_IDLE;
1409 
1410  // #8 Reverse?
1411  memset(response, 0, sizeof(response));
1412  if (isSimulation())
1413  {
1414  snprintf(response, 32, "Reverse = %d\n", (simStatus[STATUS_REVERSE] == ISS_ON) ? 1 : 0);
1415  nbytes_read = strlen(response);
1416  }
1417  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1418  {
1419  tty_error_msg(errcode, errmsg, MAXRBUF);
1420  LOGF_ERROR("%s", errmsg);
1421  return false;
1422  }
1423  response[nbytes_read - 1] = '\0';
1424  LOGF_DEBUG("RES (%s)", response);
1425 
1426  int reverse;
1427  rc = sscanf(response, "%16[^=]=%d", key, &reverse);
1428  if (rc != 2)
1429  return false;
1430 
1431  StatusL[STATUS_REVERSE].s = reverse ? IPS_OK : IPS_IDLE;
1432 
1433  // If reverse is enable and switch shows disabled, let's change that
1434  // same thing is reverse is disabled but switch is enabled
1435  if ((reverse && FocusReverseS[1].s == ISS_ON) || (!reverse && FocusReverseS[0].s == ISS_ON))
1436  {
1438  FocusReverseS[0].s = (reverse == 1) ? ISS_ON : ISS_OFF;
1439  FocusReverseS[1].s = (reverse == 0) ? ISS_ON : ISS_OFF;
1440  IDSetSwitch(&FocusReverseSP, nullptr);
1441  }
1442 
1443  StatusLP.s = IPS_OK;
1444  IDSetLight(&StatusLP, nullptr);
1445 
1446  // END is reached
1447  memset(response, 0, sizeof(response));
1448  if (isSimulation())
1449  {
1450  strncpy(response, "END\n", 16);
1451  nbytes_read = strlen(response);
1452  }
1453  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1454  {
1455  tty_error_msg(errcode, errmsg, MAXRBUF);
1456  LOGF_ERROR("%s", errmsg);
1457  return false;
1458  }
1459 
1460  if (nbytes_read > 0)
1461  {
1462  response[nbytes_read - 1] = '\0';
1463 
1464  // Display the response to be sure to have read the complet TTY Buffer.
1465  LOGF_DEBUG("RES (%s)", response);
1466  if (strcmp(response, "END"))
1467  return false;
1468  }
1469 
1470  tcflush(PortFD, TCIFLUSH);
1471 
1472  return true;
1473  }
1474  return false;
1475 }
1476 
1477 /************************************************************************************
1478  *
1479 * ***********************************************************************************/
1480 bool FocusLynxBase::getFocusTemp()
1481 {
1482  // Get value related to Temperature compensation
1483 
1484  char cmd[LYNX_MAX] = {0};
1485  int errcode = 0;
1486  char errmsg[MAXRBUF];
1487  char response[LYNX_MAX] = {0};
1488  int nbytes_read = 0;
1489  int nbytes_written = 0;
1490  char key[16];
1491 
1492  memset(response, 0, sizeof(response));
1493 
1494  snprintf(cmd, LYNX_MAX, "<%sGETTCI>", getFocusTarget());
1495  LOGF_DEBUG("CMD (%s)", cmd);
1496 
1497  if (isSimulation())
1498  {
1499  if (!strcmp(getFocusTarget(), "F1"))
1500  strncpy(response, "TEMP COMP1", 16);
1501  else
1502  strncpy(response, "TEMP COMP2", 16);
1503  nbytes_read = strlen(response) + 1;
1504  }
1505  else
1506  {
1507  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1508  {
1509  tty_error_msg(errcode, errmsg, MAXRBUF);
1510  LOGF_ERROR("%s", errmsg);
1511  return false;
1512  }
1513 
1514  if (!isResponseOK())
1515  return false;
1516 
1517  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1518  {
1519  tty_error_msg(errcode, errmsg, MAXRBUF);
1520  LOGF_ERROR("%s", errmsg);
1521  return false;
1522  }
1523  }
1524 
1525  if (nbytes_read > 0)
1526  {
1527  response[nbytes_read - 1] = '\0';
1528  LOGF_DEBUG("RES (%s)", response);
1529 
1530  if ((strcmp(response, "TEMP COMP1")) && (strcmp(response, "TEMP COMP2")))
1531  return false;
1532 
1533  memset(response, 0, sizeof(response));
1534 
1535  // Temperature Compensation On?
1536  if (isSimulation())
1537  {
1538  snprintf(response, 32, "TComp ON = %d\n", TemperatureCompensateS[0].s == ISS_ON ? 1 : 0);
1539  nbytes_read = strlen(response);
1540  }
1541  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1542  {
1543  tty_error_msg(errcode, errmsg, MAXRBUF);
1544  LOGF_ERROR("%s", errmsg);
1545  return false;
1546  }
1547  response[nbytes_read - 1] = '\0';
1548  LOGF_DEBUG("RES (%s)", response);
1549 
1550  int TCompOn;
1551  int rc = sscanf(response, "%16[^=]=%d", key, &TCompOn);
1552  if (rc != 2)
1553  return false;
1554 
1555  IUResetSwitch(&TemperatureCompensateSP);
1556  TemperatureCompensateS[0].s = TCompOn ? ISS_ON : ISS_OFF;
1557  TemperatureCompensateS[1].s = TCompOn ? ISS_OFF : ISS_ON;
1558  TemperatureCompensateSP.s = IPS_OK;
1559  IDSetSwitch(&TemperatureCompensateSP, nullptr);
1560 
1561  memset(response, 0, sizeof(response));
1562 
1563  // Temperature Compensation Mode
1564  if (isSimulation())
1565  {
1566  snprintf(response, 32, "TC Mode = %c\n", 'C');
1567  nbytes_read = strlen(response);
1568  }
1569  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1570  {
1571  tty_error_msg(errcode, errmsg, MAXRBUF);
1572  LOGF_ERROR("%s", errmsg);
1573  return false;
1574  }
1575  response[nbytes_read - 1] = '\0';
1576  LOGF_DEBUG("RES (%s)", response);
1577 
1578  char compensateMode;
1579  rc = sscanf(response, "%16[^=]= %c", key, &compensateMode);
1580  if (rc != 2)
1581  {
1582  if (rc == 1 && key[0] == 'T')
1583  {
1584  //If the controller does not support this it could be null. Assume A mode in this case.
1585  compensateMode = 'A';
1586  }
1587  else
1588  {
1589  return false;
1590  }
1591  }
1592 
1593  IUResetSwitch(&TemperatureCompensateModeSP);
1594  int index = compensateMode - 'A';
1595  if (index >= 0 && index <= 5)
1596  {
1597  TemperatureCompensateModeS[index].s = ISS_ON;
1598  TemperatureCompensateModeSP.s = IPS_OK;
1599  }
1600  else
1601  {
1602  LOGF_ERROR("Invalid index %d for compensation mode.", index);
1603  TemperatureCompensateModeSP.s = IPS_ALERT;
1604  }
1605 
1606  IDSetSwitch(&TemperatureCompensateModeSP, nullptr);
1607 
1608 
1609  // Temperature Compensation on Start
1610  memset(response, 0, sizeof(response));
1611  if (isSimulation())
1612  {
1613  snprintf(response, 32, "TC@Start = %d\n", TemperatureCompensateOnStartS[0].s == ISS_ON ? 1 : 0);
1614  nbytes_read = strlen(response);
1615  }
1616  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1617  {
1618  tty_error_msg(errcode, errmsg, MAXRBUF);
1619  LOGF_ERROR("%s", errmsg);
1620  return false;
1621  }
1622  response[nbytes_read - 1] = '\0';
1623  LOGF_DEBUG("RES (%s)", response);
1624 
1625  int TCOnStart;
1626  rc = sscanf(response, "%16[^=]=%d", key, &TCOnStart);
1627  if (rc != 2)
1628  return false;
1629 
1630  IUResetSwitch(&TemperatureCompensateOnStartSP);
1631  TemperatureCompensateOnStartS[0].s = TCOnStart ? ISS_ON : ISS_OFF;
1632  TemperatureCompensateOnStartS[1].s = TCOnStart ? ISS_OFF : ISS_ON;
1633  TemperatureCompensateOnStartSP.s = IPS_OK;
1634  IDSetSwitch(&TemperatureCompensateOnStartSP, nullptr);
1635 
1636  // Temperature Coeff A
1637  if (isSimulation())
1638  {
1639  snprintf(response, 32, "TempCo A = %d\n", static_cast<int>(TemperatureParamN[0].value));
1640  nbytes_read = strlen(response);
1641  }
1642  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1643  {
1644  tty_error_msg(errcode, errmsg, MAXRBUF);
1645  LOGF_ERROR("%s", errmsg);
1646  return false;
1647  }
1648 
1649  if (TemperatureCompensateModeS[0].s == ISS_ON)
1650  {
1651  response[nbytes_read - 1] = '\0';
1652  LOGF_DEBUG("RES (%s)", response);
1653 
1654  int TCoeff;
1655  rc = sscanf(response, "%16[^=]=%d", key, &TCoeff);
1656  if (rc != 2)
1657  return false;
1658 
1659  TemperatureParamN[0].value = TCoeff;
1660  }
1661  memset(response, 0, sizeof(response));
1662 
1663  // Temperature Coeff B
1664  if (isSimulation())
1665  {
1666  snprintf(response, 32, "TempCo B = %d\n", static_cast<int>(TemperatureParamN[0].value));
1667  nbytes_read = strlen(response);
1668  }
1669  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1670  {
1671  tty_error_msg(errcode, errmsg, MAXRBUF);
1672  LOGF_ERROR("%s", errmsg);
1673  return false;
1674  }
1675  if (TemperatureCompensateModeS[1].s == ISS_ON)
1676  {
1677  response[nbytes_read - 1] = '\0';
1678  LOGF_DEBUG("RES (%s)", response);
1679 
1680  int TCoeff;
1681  rc = sscanf(response, "%16[^=]=%d", key, &TCoeff);
1682  if (rc != 2)
1683  return false;
1684 
1685  TemperatureParamN[0].value = TCoeff;
1686  }
1687 
1688  memset(response, 0, sizeof(response));
1689 
1690  // Temperature Coeff C
1691  if (isSimulation())
1692  {
1693  snprintf(response, 32, "TempCo C = %d\n", static_cast<int>(TemperatureParamN[0].value));
1694  nbytes_read = strlen(response);
1695  }
1696  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1697  {
1698  tty_error_msg(errcode, errmsg, MAXRBUF);
1699  LOGF_ERROR("%s", errmsg);
1700  return false;
1701  }
1702  if (TemperatureCompensateModeS[2].s == ISS_ON)
1703  {
1704  response[nbytes_read - 1] = '\0';
1705  LOGF_DEBUG("RES (%s)", response);
1706 
1707  int TCoeff;
1708  rc = sscanf(response, "%16[^=]=%d", key, &TCoeff);
1709  if (rc != 2)
1710  return false;
1711 
1712  TemperatureParamN[0].value = TCoeff;
1713  }
1714 
1715  memset(response, 0, sizeof(response));
1716 
1717  // Temperature Coeff D
1718  if (isSimulation())
1719  {
1720  snprintf(response, 32, "TempCo D = %d\n", static_cast<int>(TemperatureParamN[0].value));
1721  nbytes_read = strlen(response);
1722  }
1723  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1724  {
1725  tty_error_msg(errcode, errmsg, MAXRBUF);
1726  LOGF_ERROR("%s", errmsg);
1727  return false;
1728  }
1729  if (TemperatureCompensateModeS[3].s == ISS_ON)
1730  {
1731  response[nbytes_read - 1] = '\0';
1732  LOGF_DEBUG("RES (%s)", response);
1733 
1734  int TCoeff;
1735  rc = sscanf(response, "%16[^=]=%d", key, &TCoeff);
1736  if (rc != 2)
1737  return false;
1738 
1739  TemperatureParamN[0].value = TCoeff;
1740  }
1741 
1742  memset(response, 0, sizeof(response));
1743 
1744  // Temperature Coeff E
1745  if (isSimulation())
1746  {
1747  snprintf(response, 32, "TempCo E = %d\n", static_cast<int>(TemperatureParamN[0].value));
1748  nbytes_read = strlen(response);
1749  }
1750  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1751  {
1752  tty_error_msg(errcode, errmsg, MAXRBUF);
1753  LOGF_ERROR("%s", errmsg);
1754  return false;
1755  }
1756  if (TemperatureCompensateModeS[4].s == ISS_ON)
1757  {
1758  response[nbytes_read - 1] = '\0';
1759  LOGF_DEBUG("RES (%s)", response);
1760 
1761  int TCoeff;
1762  rc = sscanf(response, "%16[^=]=%d", key, &TCoeff);
1763  if (rc != 2)
1764  return false;
1765 
1766  TemperatureParamN[0].value = TCoeff;
1767  }
1768 
1769  memset(response, 0, sizeof(response));
1770 
1771  // Temperature intercepts A
1772  if (isSimulation())
1773  {
1774  snprintf(response, 32, "TempIn A = %d\n", static_cast<int>(TemperatureParamN[1].value));
1775  nbytes_read = strlen(response);
1776  }
1777  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1778  {
1779  tty_error_msg(errcode, errmsg, MAXRBUF);
1780  LOGF_ERROR("%s", errmsg);
1781  return false;
1782  }
1783  if (TemperatureCompensateModeS[0].s == ISS_ON)
1784  {
1785  response[nbytes_read - 1] = '\0';
1786  LOGF_DEBUG("RES (%s)", response);
1787 
1788  int TInter;
1789  rc = sscanf(response, "%16[^=]=%d", key, &TInter);
1790  if (rc != 2)
1791  return false;
1792 
1793  TemperatureParamN[1].value = TInter;
1794  }
1795 
1796  memset(response, 0, sizeof(response));
1797 
1798  // Temperature intercepts B
1799  if (isSimulation())
1800  {
1801  snprintf(response, 32, "TempIn B = %d\n", static_cast<int>(TemperatureParamN[1].value));
1802  nbytes_read = strlen(response);
1803  }
1804  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1805  {
1806  tty_error_msg(errcode, errmsg, MAXRBUF);
1807  LOGF_ERROR("%s", errmsg);
1808  return false;
1809  }
1810  if (TemperatureCompensateModeS[1].s == ISS_ON)
1811  {
1812  response[nbytes_read - 1] = '\0';
1813  LOGF_DEBUG("RES (%s)", response);
1814 
1815  int TInter;
1816  rc = sscanf(response, "%16[^=]=%d", key, &TInter);
1817  if (rc != 2)
1818  return false;
1819 
1820  TemperatureParamN[1].value = TInter;
1821  }
1822 
1823  memset(response, 0, sizeof(response));
1824 
1825  // Temperature intercepts C
1826  if (isSimulation())
1827  {
1828  snprintf(response, 32, "TempIn C = %d\n", static_cast<int>(TemperatureParamN[1].value));
1829  nbytes_read = strlen(response);
1830  }
1831  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1832  {
1833  tty_error_msg(errcode, errmsg, MAXRBUF);
1834  LOGF_ERROR("%s", errmsg);
1835  return false;
1836  }
1837  if (TemperatureCompensateModeS[2].s == ISS_ON)
1838  {
1839  response[nbytes_read - 1] = '\0';
1840  LOGF_DEBUG("RES (%s)", response);
1841 
1842  int TInter;
1843  rc = sscanf(response, "%16[^=]=%d", key, &TInter);
1844  if (rc != 2)
1845  return false;
1846 
1847  TemperatureParamN[1].value = TInter;
1848  }
1849 
1850  memset(response, 0, sizeof(response));
1851 
1852  // Temperature intercepts D
1853  if (isSimulation())
1854  {
1855  snprintf(response, 32, "TempIn D = %d\n", static_cast<int>(TemperatureParamN[1].value));
1856  nbytes_read = strlen(response);
1857  }
1858  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1859  {
1860  tty_error_msg(errcode, errmsg, MAXRBUF);
1861  LOGF_ERROR("%s", errmsg);
1862  return false;
1863  }
1864  if (TemperatureCompensateModeS[3].s == ISS_ON)
1865  {
1866  response[nbytes_read - 1] = '\0';
1867  LOGF_DEBUG("RES (%s)", response);
1868 
1869  int TInter;
1870  rc = sscanf(response, "%16[^=]=%d", key, &TInter);
1871  if (rc != 2)
1872  return false;
1873 
1874  TemperatureParamN[1].value = TInter;
1875  }
1876 
1877  memset(response, 0, sizeof(response));
1878 
1879  // Temperature intercepts E
1880  if (isSimulation())
1881  {
1882  snprintf(response, 32, "TempIn E = %d\n", static_cast<int>(TemperatureParamN[1].value));
1883  nbytes_read = strlen(response);
1884  }
1885  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1886  {
1887  tty_error_msg(errcode, errmsg, MAXRBUF);
1888  LOGF_ERROR("%s", errmsg);
1889  return false;
1890  }
1891  if (TemperatureCompensateModeS[4].s == ISS_ON)
1892  {
1893  response[nbytes_read - 1] = '\0';
1894  LOGF_DEBUG("RES (%s)", response);
1895 
1896  int TInter;
1897  rc = sscanf(response, "%16[^=]=%d", key, &TInter);
1898  if (rc != 2)
1899  return false;
1900 
1901  TemperatureParamN[1].value = TInter;
1902  }
1903 
1904  TemperatureParamNP.s = IPS_OK;
1905  IDSetNumber(&TemperatureParamNP, nullptr);
1906 
1907  memset(response, 0, sizeof(response));
1908 
1909  // StepSize
1910  if (isSimulation())
1911  {
1912  snprintf(response, 32, "StepSize = %d\n", static_cast<int>(StepSizeN[0].value));
1913  nbytes_read = strlen(response);
1914  }
1915  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1916  {
1917  tty_error_msg(errcode, errmsg, MAXRBUF);
1918  LOGF_ERROR("%s", errmsg);
1919  return false;
1920  }
1921  response[nbytes_read - 1] = '\0';
1922  LOGF_DEBUG("RES (%s)", response);
1923 
1924  int valueStepSize;
1925  rc = sscanf(response, "%16[^=]=%d", key, &valueStepSize);
1926  if (rc != 2)
1927  return false;
1928 
1929  StepSizeN[0].value = valueStepSize;
1930  IDSetNumber(&StepSizeNP, nullptr);
1931 
1932  memset(response, 0, sizeof(response));
1933 
1934  // END is reached
1935  memset(response, 0, sizeof(response));
1936  if (isSimulation())
1937  {
1938  strncpy(response, "END\n", 16);
1939  nbytes_read = strlen(response);
1940  }
1941  else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1942  {
1943  tty_error_msg(errcode, errmsg, MAXRBUF);
1944  LOGF_ERROR("%s", errmsg);
1945  return false;
1946  }
1947 
1948  if (nbytes_read > 0)
1949  {
1950  response[nbytes_read - 1] = '\0';
1951 
1952  // Display the response to be sure to have read the complet TTY Buffer.
1953  LOGF_DEBUG("RES (%s)", response);
1954  if (strcmp(response, "END"))
1955  return false;
1956  }
1957 
1958  tcflush(PortFD, TCIFLUSH);
1959 
1960  return true;
1961  }
1962  return false;
1963 }
1964 
1965 /************************************************************************************
1966  *
1967 * ***********************************************************************************/
1969 {
1970  char cmd[16];
1971  int errcode = 0;
1972  char errmsg[MAXRBUF];
1973  char response[LYNX_MAX] = {0};
1974  int nbytes_read = 0;
1975  int nbytes_written = 0;
1976 
1977  memset(response, 0, sizeof(response));
1978 
1979  snprintf(cmd, 16, "<%sSCDT%s>", getFocusTarget(), index > 0 ? lynxModels[ModelS[index].name].c_str() : "ZZ");
1980 
1981  LOGF_DEBUG("CMD (%s)", cmd);
1982 
1983  if (isSimulation())
1984  {
1985  strncpy(response, "SET", 16);
1986  nbytes_read = strlen(response) + 1;
1987  }
1988  else
1989  {
1990  tcflush(PortFD, TCIFLUSH);
1991 
1992  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1993  {
1994  tty_error_msg(errcode, errmsg, MAXRBUF);
1995  LOGF_ERROR("%s", errmsg);
1996  return false;
1997  }
1998 
1999  if (!isResponseOK())
2000  return false;
2001 
2002  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2003  {
2004  tty_error_msg(errcode, errmsg, MAXRBUF);
2005  LOGF_ERROR("%s", errmsg);
2006  return false;
2007  }
2008  }
2009 
2010  if (nbytes_read > 0)
2011  {
2012  response[nbytes_read - 1] = '\0';
2013  LOGF_DEBUG("RES (%s)", response);
2014  tcflush(PortFD, TCIFLUSH);
2015 
2016  if (!strcmp(response, "SET"))
2017  return true;
2018  else
2019  return false;
2020  }
2021 
2022  return false;
2023 }
2024 
2025 /************************************************************************************
2026  *
2027 * ***********************************************************************************/
2028 bool FocusLynxBase::setLedLevel(int level)
2029 // Write via the connected port to the HUB the selected LED intensity level
2030 
2031 {
2032  char cmd[16];
2033  int errcode = 0;
2034  char errmsg[MAXRBUF];
2035  char response[LYNX_MAX] = {0};
2036  int nbytes_read = 0;
2037  int nbytes_written = 0;
2038 
2039  memset(response, 0, sizeof(response));
2040 
2041  snprintf(cmd, 16, "<FHSCLB%d>", level);
2042 
2043  LOGF_DEBUG("CMD (%s)", cmd);
2044 
2045  if (isSimulation())
2046  {
2047  strncpy(response, "SET", 16);
2048  nbytes_read = strlen(response) + 1;
2049  }
2050  else
2051  {
2052  tcflush(PortFD, TCIFLUSH);
2053 
2054  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2055  {
2056  tty_error_msg(errcode, errmsg, MAXRBUF);
2057  LOGF_ERROR("%s", errmsg);
2058  return false;
2059  }
2060 
2061  if (!isResponseOK())
2062  return false;
2063 
2064  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2065  {
2066  tty_error_msg(errcode, errmsg, MAXRBUF);
2067  LOGF_ERROR("%s", errmsg);
2068  return false;
2069  }
2070  }
2071 
2072  if (nbytes_read > 0)
2073  {
2074  response[nbytes_read - 1] = '\0';
2075  LOGF_DEBUG("RES (%s)", response);
2076  tcflush(PortFD, TCIFLUSH);
2077 
2078  if (!strcmp(response, "SET"))
2079  return true;
2080  else
2081  return false;
2082  }
2083 
2084  return false;
2085 }
2086 
2087 /************************************************************************************
2088  *
2089 * ***********************************************************************************/
2090 bool FocusLynxBase::setDeviceNickname(const char *nickname)
2091 // Write via the connected port to the HUB the choiced nikname of the focuser
2092 {
2093  char cmd[LYNX_MAX] = {0};
2094  int errcode = 0;
2095  char errmsg[MAXRBUF];
2096  char response[LYNX_MAX] = {0};
2097  int nbytes_read = 0;
2098  int nbytes_written = 0;
2099 
2100  memset(response, 0, sizeof(response));
2101 
2102  snprintf(cmd, LYNX_MAX, "<%sSCNN%s>", getFocusTarget(), nickname);
2103 
2104  LOGF_DEBUG("CMD (%s)", cmd);
2105 
2106  if (isSimulation())
2107  {
2108  strncpy(response, "SET", 16);
2109  nbytes_read = strlen(response) + 1;
2110  }
2111  else
2112  {
2113  tcflush(PortFD, TCIFLUSH);
2114 
2115  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2116  {
2117  tty_error_msg(errcode, errmsg, MAXRBUF);
2118  LOGF_ERROR("%s", errmsg);
2119  return false;
2120  }
2121 
2122  if (!isResponseOK())
2123  return false;
2124 
2125  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2126  {
2127  tty_error_msg(errcode, errmsg, MAXRBUF);
2128  LOGF_ERROR("%s", errmsg);
2129  return false;
2130  }
2131  }
2132 
2133  if (nbytes_read > 0)
2134  {
2135  response[nbytes_read - 1] = '\0';
2136  LOGF_DEBUG("RES (%s)", response);
2137  tcflush(PortFD, TCIFLUSH);
2138 
2139  if (!strcmp(response, "SET"))
2140  return true;
2141  else
2142  return false;
2143  }
2144 
2145  return false;
2146 }
2147 /************************************************************************************
2148  *
2149 * ***********************************************************************************/
2150 bool FocusLynxBase::home()
2151 {
2152  char cmd[LYNX_MAX] = {0};
2153  int errcode = 0;
2154  char errmsg[MAXRBUF];
2155  char response[LYNX_MAX] = {0};
2156  int nbytes_read = 0;
2157  int nbytes_written = 0;
2158 
2159  memset(response, 0, sizeof(response));
2160 
2161  snprintf(cmd, LYNX_MAX, "<%sHOME>", getFocusTarget());
2162  LOGF_DEBUG("CMD (%s)", cmd);
2163 
2164  if (isSimulation())
2165  {
2166  strncpy(response, "H", 16);
2167  nbytes_read = strlen(response) + 1;
2168  targetPosition = 0;
2169  //FocusAbsPosN[0].value = MaxTravelN[0].value;
2171  IDSetNumber(&FocusAbsPosNP, nullptr);
2172  simStatus[STATUS_HOMING] = ISS_ON;
2173  simStatus[STATUS_HOMED] = ISS_OFF;
2174  simPosition = FocusAbsPosN[0].value;
2175  }
2176  else
2177  {
2178  tcflush(PortFD, TCIFLUSH);
2179 
2180  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2181  {
2182  tty_error_msg(errcode, errmsg, MAXRBUF);
2183  LOGF_ERROR("%s", errmsg);
2184  return false;
2185  }
2186 
2187  if (!isResponseOK())
2188  return false;
2189 
2190  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2191  {
2192  tty_error_msg(errcode, errmsg, MAXRBUF);
2193  LOGF_ERROR("%s", errmsg);
2194  return false;
2195  }
2196  }
2197 
2198  if (nbytes_read > 0)
2199  {
2200  response[nbytes_read - 1] = '\0';
2201  LOGF_DEBUG("RES (%s)", response);
2203  IDSetNumber(&FocusAbsPosNP, nullptr);
2204 
2205  isHoming = true;
2206  LOG_INFO("Focuser is homing...");
2207 
2208  tcflush(PortFD, TCIFLUSH);
2209 
2210  return true;
2211  }
2212 
2213  return false;
2214 }
2215 
2216 /************************************************************************************
2217  *
2218 * ***********************************************************************************/
2219 bool FocusLynxBase::center()
2220 {
2221  char cmd[LYNX_MAX] = {0};
2222  int errcode = 0;
2223  char errmsg[MAXRBUF];
2224  char response[LYNX_MAX] = {0};
2225  int nbytes_read = 0;
2226  int nbytes_written = 0;
2227 
2228  memset(response, 0, sizeof(response));
2229 
2230  snprintf(cmd, LYNX_MAX, "<%sCENTER>", getFocusTarget());
2231  LOGF_DEBUG("CMD (%s)", cmd);
2232 
2233  if (isSimulation())
2234  {
2235  strncpy(response, "M", 16);
2236  nbytes_read = strlen(response) + 1;
2237  simStatus[STATUS_MOVING] = ISS_ON;
2238  targetPosition = FocusAbsPosN[0].max / 2;
2239  }
2240  else
2241  {
2242  tcflush(PortFD, TCIFLUSH);
2243 
2244  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2245  {
2246  tty_error_msg(errcode, errmsg, MAXRBUF);
2247  LOGF_ERROR("%s", errmsg);
2248  return false;
2249  }
2250 
2251  if (!isResponseOK())
2252  return false;
2253 
2254  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2255  {
2256  tty_error_msg(errcode, errmsg, MAXRBUF);
2257  LOGF_ERROR("%s", errmsg);
2258  return false;
2259  }
2260  }
2261 
2262  if (nbytes_read > 0)
2263  {
2264  response[nbytes_read - 1] = '\0';
2265  LOGF_DEBUG("RES (%s)", response);
2266 
2267  LOG_INFO("Focuser moving to center position...");
2268 
2270  IDSetNumber(&FocusAbsPosNP, nullptr);
2271 
2272  tcflush(PortFD, TCIFLUSH);
2273 
2274  return true;
2275  }
2276 
2277  return false;
2278 }
2279 
2280 /************************************************************************************
2281  *
2282 * ***********************************************************************************/
2283 bool FocusLynxBase::setTemperatureCompensation(bool enable)
2284 {
2285  char cmd[16];
2286  int errcode = 0;
2287  char errmsg[MAXRBUF];
2288  char response[LYNX_MAX] = {0};
2289  int nbytes_read = 0;
2290  int nbytes_written = 0;
2291 
2292  memset(response, 0, sizeof(response));
2293 
2294  snprintf(cmd, 16, "<%sSCTE%d>", getFocusTarget(), enable ? 1 : 0);
2295 
2296  LOGF_DEBUG("CMD (%s)", cmd);
2297 
2298  if (isSimulation())
2299  {
2300  strncpy(response, "SET", 16);
2301  nbytes_read = strlen(response) + 1;
2302  }
2303  else
2304  {
2305  tcflush(PortFD, TCIFLUSH);
2306 
2307  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2308  {
2309  tty_error_msg(errcode, errmsg, MAXRBUF);
2310  LOGF_ERROR("%s", errmsg);
2311  return false;
2312  }
2313 
2314  if (!isResponseOK())
2315  return false;
2316 
2317  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2318  {
2319  tty_error_msg(errcode, errmsg, MAXRBUF);
2320  LOGF_ERROR("%s", errmsg);
2321  return false;
2322  }
2323  }
2324 
2325  if (nbytes_read > 0)
2326  {
2327  response[nbytes_read - 1] = '\0';
2328  LOGF_DEBUG("RES (%s)", response);
2329  tcflush(PortFD, TCIFLUSH);
2330 
2331  if (!strcmp(response, "SET"))
2332  return true;
2333  else
2334  return false;
2335  }
2336 
2337  return false;
2338 }
2339 
2340 /************************************************************************************
2341  *
2342 * ***********************************************************************************/
2343 bool FocusLynxBase::setTemperatureCompensationMode(char mode)
2344 {
2345  char cmd[16];
2346  int errcode = 0;
2347  char errmsg[MAXRBUF];
2348  char response[LYNX_MAX] = {0};
2349  int nbytes_read = 0;
2350  int nbytes_written = 0;
2351 
2352  memset(response, 0, sizeof(response));
2353 
2354  snprintf(cmd, 16, "<%sSCTM%c>", getFocusTarget(), mode);
2355 
2356  LOGF_DEBUG("CMD (%s)", cmd);
2357 
2358  if (isSimulation())
2359  {
2360  strncpy(response, "SET", 16);
2361  nbytes_read = strlen(response) + 1;
2362  }
2363  else
2364  {
2365  tcflush(PortFD, TCIFLUSH);
2366 
2367  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2368  {
2369  tty_error_msg(errcode, errmsg, MAXRBUF);
2370  LOGF_ERROR("%s", errmsg);
2371  return false;
2372  }
2373 
2374  if (!isResponseOK())
2375  return false;
2376 
2377  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2378  {
2379  tty_error_msg(errcode, errmsg, MAXRBUF);
2380  LOGF_ERROR("%s", errmsg);
2381  return false;
2382  }
2383  }
2384 
2385  if (nbytes_read > 0)
2386  {
2387  response[nbytes_read - 1] = '\0';
2388  LOGF_DEBUG("RES (%s)", response);
2389  tcflush(PortFD, TCIFLUSH);
2390 
2391  // If OK, the value would be read and update UI properties
2392  if (!strcmp(response, "SET"))
2393  return getFocusTemp();
2394  else
2395  return false;
2396  }
2397 
2398  return false;
2399 }
2400 
2401 /************************************************************************************
2402  *
2403 * ***********************************************************************************/
2404 bool FocusLynxBase::setTemperatureCompensationCoeff(char mode, int16_t coeff)
2405 {
2406  char cmd[16];
2407  int errcode = 0;
2408  char errmsg[MAXRBUF];
2409  char response[LYNX_MAX] = {0};
2410  int nbytes_read = 0;
2411  int nbytes_written = 0;
2412 
2413  memset(response, 0, sizeof(response));
2414 
2415  snprintf(cmd, 16, "<%sSCTC%c%c%04d>", getFocusTarget(), mode, coeff >= 0 ? '+' : '-', static_cast<int>(std::abs(coeff)));
2416 
2417  LOGF_DEBUG("CMD (%s)", cmd);
2418 
2419  if (isSimulation())
2420  {
2421  strncpy(response, "SET", 16);
2422  nbytes_read = strlen(response) + 1;
2423  }
2424  else
2425  {
2426  tcflush(PortFD, TCIFLUSH);
2427 
2428  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2429  {
2430  tty_error_msg(errcode, errmsg, MAXRBUF);
2431  LOGF_ERROR("%s", errmsg);
2432  return false;
2433  }
2434 
2435  if (!isResponseOK())
2436  return false;
2437 
2438  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2439  {
2440  tty_error_msg(errcode, errmsg, MAXRBUF);
2441  LOGF_ERROR("%s", errmsg);
2442  return false;
2443  }
2444  }
2445 
2446  if (nbytes_read > 0)
2447  {
2448  response[nbytes_read - 1] = '\0';
2449  LOGF_DEBUG("RES (%s)", response);
2450  tcflush(PortFD, TCIFLUSH);
2451 
2452  if (!strcmp(response, "SET"))
2453  return true;
2454  else
2455  return false;
2456  }
2457 
2458  return false;
2459 }
2460 
2461 /************************************************************************************
2462  *
2463 * ***********************************************************************************/
2464 bool FocusLynxBase::setTemperatureInceptions(char mode, int32_t inter)
2465 {
2466  char cmd[LYNX_MAX] = {0};
2467  int errcode = 0;
2468  char errmsg[MAXRBUF];
2469  char response[LYNX_MAX] = {0};
2470  int nbytes_read = 0;
2471  int nbytes_written = 0;
2472 
2473  memset(response, 0, sizeof(response));
2474 
2475  snprintf(cmd, LYNX_MAX, "<%sSETINT%c%c%06d>", getFocusTarget(), mode, inter >= 0 ? '+' : '-',
2476  static_cast<int>(std::abs(inter)));
2477 
2478  LOGF_DEBUG("CMD (%s)", cmd);
2479 
2480  if (isSimulation())
2481  {
2482  strncpy(response, "SET", 16);
2483  nbytes_read = strlen(response) + 1;
2484  }
2485  else
2486  {
2487  tcflush(PortFD, TCIFLUSH);
2488 
2489  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2490  {
2491  tty_error_msg(errcode, errmsg, MAXRBUF);
2492  LOGF_ERROR("%s", errmsg);
2493  return false;
2494  }
2495 
2496  if (!isResponseOK())
2497  return false;
2498 
2499  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2500  {
2501  tty_error_msg(errcode, errmsg, MAXRBUF);
2502  LOGF_ERROR("%s", errmsg);
2503  return false;
2504  }
2505  }
2506 
2507  if (nbytes_read > 0)
2508  {
2509  response[nbytes_read - 1] = '\0';
2510  LOGF_DEBUG("RES (%s)", response);
2511  tcflush(PortFD, TCIFLUSH);
2512 
2513  if (!strcmp(response, "SET"))
2514  return true;
2515  else
2516  return false;
2517  }
2518 
2519  return false;
2520 }
2521 
2522 /************************************************************************************
2523  *
2524 * ***********************************************************************************/
2525 bool FocusLynxBase::setTemperatureCompensationOnStart(bool enable)
2526 {
2527  char cmd[16];
2528  int errcode = 0;
2529  char errmsg[MAXRBUF];
2530  char response[LYNX_MAX] = {0};
2531  int nbytes_read = 0;
2532  int nbytes_written = 0;
2533 
2534  memset(response, 0, sizeof(response));
2535 
2536  snprintf(cmd, 16, "<%sSCTS%d>", getFocusTarget(), enable ? 1 : 0);
2537 
2538  LOGF_DEBUG("CMD (%s)", cmd);
2539 
2540  if (isSimulation())
2541  {
2542  strncpy(response, "SET", 16);
2543  nbytes_read = strlen(response) + 1;
2544  }
2545  else
2546  {
2547  tcflush(PortFD, TCIFLUSH);
2548 
2549  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2550  {
2551  tty_error_msg(errcode, errmsg, MAXRBUF);
2552  LOGF_ERROR("%s", errmsg);
2553  return false;
2554  }
2555 
2556  if (!isResponseOK())
2557  return false;
2558 
2559  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2560  {
2561  tty_error_msg(errcode, errmsg, MAXRBUF);
2562  LOGF_ERROR("%s", errmsg);
2563  return false;
2564  }
2565  }
2566 
2567  if (nbytes_read > 0)
2568  {
2569  response[nbytes_read - 1] = '\0';
2570  LOGF_DEBUG("RES (%s)", response);
2571  tcflush(PortFD, TCIFLUSH);
2572 
2573  if (!strcmp(response, "SET"))
2574  return true;
2575  else
2576  return false;
2577  }
2578 
2579  return false;
2580 }
2581 
2582 /************************************************************************************
2583  *
2584 * ***********************************************************************************/
2585 //bool FocusLynxBase::setBacklashCompensation(bool enable)
2587 {
2588  char cmd[16];
2589  int errcode = 0;
2590  char errmsg[MAXRBUF];
2591  char response[LYNX_MAX] = {0};
2592  int nbytes_read = 0;
2593  int nbytes_written = 0;
2594 
2595  memset(response, 0, sizeof(response));
2596 
2597  snprintf(cmd, 16, "<%sSCBE%d>", getFocusTarget(), enabled ? 1 : 0);
2598 
2599  LOGF_DEBUG("CMD (%s)", cmd);
2600 
2601  if (isSimulation())
2602  {
2603  strncpy(response, "SET", 16);
2604  nbytes_read = strlen(response) + 1;
2605  }
2606  else
2607  {
2608  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2609  {
2610  tty_error_msg(errcode, errmsg, MAXRBUF);
2611  LOGF_ERROR("%s", errmsg);
2612  return false;
2613  }
2614 
2615  if (!isResponseOK())
2616  return false;
2617 
2618  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2619  {
2620  tty_error_msg(errcode, errmsg, MAXRBUF);
2621  LOGF_ERROR("%s", errmsg);
2622  return false;
2623  }
2624  }
2625 
2626  if (nbytes_read > 0)
2627  {
2628  response[nbytes_read - 1] = '\0';
2629  LOGF_DEBUG("RES (%s)", response);
2630  tcflush(PortFD, TCIFLUSH);
2631 
2632  if (!strcmp(response, "SET"))
2633  return true;
2634  else
2635  return false;
2636  }
2637 
2638  return false;
2639 }
2640 
2641 /************************************************************************************
2642  *
2643 * ***********************************************************************************/
2644 //bool FocusLynxBase::setFocusBacklashSteps(uint16_t steps)
2646 {
2647  char cmd[16];
2648  int errcode = 0;
2649  char errmsg[MAXRBUF];
2650  char response[LYNX_MAX] = {0};
2651  int nbytes_read = 0;
2652  int nbytes_written = 0;
2653 
2654  memset(response, 0, sizeof(response));
2655 
2656  snprintf(cmd, 16, "<%sSCBS%02d>", getFocusTarget(), steps);
2657 
2658  LOGF_DEBUG("CMD (%s)", cmd);
2659 
2660  if (isSimulation())
2661  {
2662  strncpy(response, "SET", 16);
2663  nbytes_read = strlen(response) + 1;
2664  }
2665  else
2666  {
2667  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2668  {
2669  tty_error_msg(errcode, errmsg, MAXRBUF);
2670  LOGF_ERROR("%s", errmsg);
2671  return false;
2672  }
2673 
2674  if (!isResponseOK())
2675  return false;
2676 
2677  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2678  {
2679  tty_error_msg(errcode, errmsg, MAXRBUF);
2680  LOGF_ERROR("%s", errmsg);
2681  return false;
2682  }
2683  }
2684 
2685  if (nbytes_read > 0)
2686  {
2687  response[nbytes_read - 1] = '\0';
2688  LOGF_DEBUG("RES (%s)", response);
2689  tcflush(PortFD, TCIFLUSH);
2690 
2691  if (!strcmp(response, "SET"))
2692  return true;
2693  else
2694  return false;
2695  }
2696 
2697  return false;
2698 }
2699 
2700 /************************************************************************************
2701  *
2702 * ***********************************************************************************/
2704 {
2705  char cmd[16];
2706  int errcode = 0;
2707  char errmsg[MAXRBUF];
2708  char response[LYNX_MAX] = {0};
2709  int nbytes_read = 0;
2710  int nbytes_written = 0;
2711 
2712  memset(response, 0, sizeof(response));
2713 
2714  snprintf(cmd, 16, "<%sREVERSE%d>", getFocusTarget(), enabled ? 1 : 0);
2715 
2716  LOGF_DEBUG("CMD (%s)", cmd);
2717 
2718  if (isSimulation())
2719  {
2720  strncpy(response, "SET", 16);
2721  nbytes_read = strlen(response) + 1;
2722  simStatus[STATUS_REVERSE] = enabled ? ISS_ON : ISS_OFF;
2723  }
2724  else
2725  {
2726  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2727  {
2728  tty_error_msg(errcode, errmsg, MAXRBUF);
2729  LOGF_ERROR("%s", errmsg);
2730  return false;
2731  }
2732 
2733  if (!isResponseOK())
2734  return false;
2735 
2736  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2737  {
2738  tty_error_msg(errcode, errmsg, MAXRBUF);
2739  LOGF_ERROR("%s", errmsg);
2740  return false;
2741  }
2742  }
2743 
2744  if (nbytes_read > 0)
2745  {
2746  response[nbytes_read - 1] = '\0';
2747  LOGF_DEBUG("RES (%s)", response);
2748  tcflush(PortFD, TCIFLUSH);
2749 
2750  if (!strcmp(response, "SET"))
2751  return true;
2752  else
2753  return false;
2754  }
2755 
2756  return false;
2757 }
2758 
2759 /************************************************************************************
2760  *
2761 * ***********************************************************************************/
2762 bool FocusLynxBase::SyncFocuser(uint32_t ticks)
2763 {
2764  char cmd[LYNX_MAX] = {0};
2765  int errcode = 0;
2766  char errmsg[MAXRBUF];
2767  char response[LYNX_MAX] = {0};
2768  int nbytes_read = 0;
2769  int nbytes_written = 0;
2770 
2771  memset(response, 0, sizeof(response));
2772 
2773  snprintf(cmd, LYNX_MAX, "<%sSCCP%06d>", getFocusTarget(), ticks);
2774  LOGF_DEBUG("CMD (%s)", cmd);
2775 
2776  if (isSimulation())
2777  {
2778  simPosition = ticks;
2779  strncpy(response, "SET", 16);
2780  nbytes_read = strlen(response) + 1;
2781  }
2782  else
2783  {
2784  tcflush(PortFD, TCIFLUSH);
2785 
2786  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2787  {
2788  tty_error_msg(errcode, errmsg, MAXRBUF);
2789  LOGF_ERROR("%s", errmsg);
2790  return false;
2791  }
2792 
2793  if (!isResponseOK())
2794  return false;
2795 
2796  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2797  {
2798  tty_error_msg(errcode, errmsg, MAXRBUF);
2799  LOGF_ERROR("%s", errmsg);
2800  return false;
2801  }
2802  }
2803 
2804  if (nbytes_read > 0)
2805  {
2806  response[nbytes_read - 1] = '\0';
2807  LOGF_DEBUG("RES (%s)", response);
2808  tcflush(PortFD, TCIFLUSH);
2809 
2810  if (!strcmp(response, "SET"))
2811  {
2812  LOGF_INFO("Setting current position to %d", ticks);
2813  return true;
2814  }
2815  else
2816  return false;
2817  }
2818  return false;
2819 }
2820 
2821 /************************************************************************************
2822  *
2823 * ***********************************************************************************/
2824 //bool FocusLynxBase::setMaxTravel(u_int16_t travel)
2826 {
2827  char cmd[LYNX_MAX] = {0};
2828  int errcode = 0;
2829  char errmsg[MAXRBUF];
2830  char response[LYNX_MAX] = {0};
2831  int nbytes_read = 0;
2832  int nbytes_written = 0;
2833 
2834  memset(response, 0, sizeof(response));
2835 
2836  snprintf(cmd, LYNX_MAX, "<%sSETMAX%06d>", getFocusTarget(), ticks);
2837  LOGF_DEBUG("CMD (%s)", cmd);
2838 
2839  SyncPresets(ticks);
2840 
2841  if (isSimulation())
2842  {
2843  strncpy(response, "SET", 16);
2844  nbytes_read = strlen(response) + 1;
2845  }
2846  else
2847  {
2848  tcflush(PortFD, TCIFLUSH);
2849 
2850  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2851  {
2852  tty_error_msg(errcode, errmsg, MAXRBUF);
2853  LOGF_ERROR("%s", errmsg);
2854  return false;
2855  }
2856 
2857  if (!isResponseOK())
2858  return false;
2859 
2860  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2861  {
2862  tty_error_msg(errcode, errmsg, MAXRBUF);
2863  LOGF_ERROR("%s", errmsg);
2864  return false;
2865  }
2866  }
2867 
2868  if (nbytes_read > 0)
2869  {
2870  response[nbytes_read - 1] = '\0';
2871  LOGF_DEBUG("RES (%s)", response);
2872  tcflush(PortFD, TCIFLUSH);
2873 
2874  if (!strcmp(response, "SET"))
2875  {
2876  getFocusConfig();
2877  return true;
2878  }
2879  else
2880  return false;
2881  }
2882 
2883  return false;
2884 }
2885 
2886 /************************************************************************************
2887  *
2888 * ***********************************************************************************/
2889 bool FocusLynxBase::setStepSize(u_int16_t stepsize)
2890 {
2891  char cmd[LYNX_MAX] = {0};
2892  int errcode = 0;
2893  char errmsg[MAXRBUF];
2894  char response[LYNX_MAX] = {0};
2895  int nbytes_read = 0;
2896  int nbytes_written = 0;
2897 
2898  memset(response, 0, sizeof(response));
2899 
2900  snprintf(cmd, LYNX_MAX, "<%sSETFSS%06d>", getFocusTarget(), stepsize);
2901  LOGF_DEBUG("CMD (%s)", cmd);
2902 
2903  if (isSimulation())
2904  {
2905  strncpy(response, "SET", 16);
2906  nbytes_read = strlen(response) + 1;
2907  }
2908  else
2909  {
2910  tcflush(PortFD, TCIFLUSH);
2911 
2912  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2913  {
2914  tty_error_msg(errcode, errmsg, MAXRBUF);
2915  LOGF_ERROR("%s", errmsg);
2916  return false;
2917  }
2918 
2919  if (!isResponseOK())
2920  return false;
2921 
2922  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2923  {
2924  tty_error_msg(errcode, errmsg, MAXRBUF);
2925  LOGF_ERROR("%s", errmsg);
2926  return false;
2927  }
2928  }
2929 
2930  if (nbytes_read > 0)
2931  {
2932  response[nbytes_read - 1] = '\0';
2933  LOGF_DEBUG("RES (%s)", response);
2934  tcflush(PortFD, TCIFLUSH);
2935 
2936  if (!strcmp(response, "SET"))
2937  {
2938  getFocusConfig();
2939  return true;
2940  }
2941  else
2942  return false;
2943  }
2944 
2945  return false;
2946 }
2947 
2948 /************************************************************************************
2949  *
2950 * ***********************************************************************************/
2951 bool FocusLynxBase::resetFactory()
2952 {
2953  char cmd[LYNX_MAX] = {0};
2954  int errcode = 0;
2955  char errmsg[MAXRBUF];
2956  char response[LYNX_MAX] = {0};
2957  int nbytes_read = 0;
2958  int nbytes_written = 0;
2959 
2960  memset(response, 0, sizeof(response));
2961 
2962  snprintf(cmd, LYNX_MAX, "<%sRESET>", getFocusTarget());
2963  LOGF_DEBUG("CMD (%s)", cmd);
2964 
2965  if (isSimulation())
2966  {
2967  strncpy(response, "SET", 16);
2968  nbytes_read = strlen(response) + 1;
2969  }
2970  else
2971  {
2972  tcflush(PortFD, TCIFLUSH);
2973 
2974  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2975  {
2976  tty_error_msg(errcode, errmsg, MAXRBUF);
2977  LOGF_ERROR("%s", errmsg);
2978  return false;
2979  }
2980 
2981  if (!isResponseOK())
2982  return false;
2983 
2984  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2985  {
2986  tty_error_msg(errcode, errmsg, MAXRBUF);
2987  LOGF_ERROR("%s", errmsg);
2988  return false;
2989  }
2990  }
2991 
2992  if (nbytes_read > 0)
2993  {
2994  response[nbytes_read - 1] = '\0';
2995  LOGF_DEBUG("RES (%s)", response);
2996  tcflush(PortFD, TCIFLUSH);
2997 
2998  if (!strcmp(response, "SET"))
2999  {
3000  getFocusConfig();
3001  return true;
3002  }
3003  else
3004  return false;
3005  }
3006 
3007  return false;
3008 }
3009 
3010 /************************************************************************************
3011  *
3012 * ***********************************************************************************/
3014 {
3015  int errcode = 0;
3016  char errmsg[MAXRBUF];
3017  char response[LYNX_MAX] = {0};
3018  int nbytes_read = 0;
3019 
3020  memset(response, 0, sizeof(response));
3021 
3022  if (isSimulation())
3023  {
3024  strcpy(response, "!");
3025  nbytes_read = strlen(response) + 1;
3026  }
3027  else
3028  {
3029  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3030  {
3031  tty_error_msg(errcode, errmsg, MAXRBUF);
3032  LOGF_ERROR("TTY error: %s", errmsg);
3033  return false;
3034  }
3035  }
3036 
3037  if (nbytes_read > 0)
3038  {
3039  response[nbytes_read - 1] = '\0';
3040  LOGF_DEBUG("RES (%s)", response);
3041 
3042  if (!strcmp(response, "!"))
3043  return true;
3044  else
3045  {
3046  memset(response, 0, sizeof(response));
3047  while (strstr(response, "END") == nullptr)
3048  {
3049  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3050  {
3051  tty_error_msg(errcode, errmsg, MAXRBUF);
3052  LOGF_ERROR("TTY error: %s", errmsg);
3053  return false;
3054  }
3055  response[nbytes_read - 1] = '\0';
3056  LOGF_ERROR("Controller error: %s", response);
3057  }
3058 
3059  return false;
3060  }
3061  }
3062  return true;
3063 }
3064 
3065 /************************************************************************************
3066 *
3067 * ***********************************************************************************/
3068 IPState FocusLynxBase::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
3069 {
3070  char cmd[16];
3071  int errcode = 0;
3072  char errmsg[MAXRBUF];
3073  char response[LYNX_MAX] = {0};
3074  int nbytes_read = 0;
3075  int nbytes_written = 0;
3076 
3077  memset(response, 0, sizeof(response));
3078 
3079  snprintf(cmd, 16, "<%sM%cR%c>", getFocusTarget(), (dir == FOCUS_INWARD) ? 'I' : 'O', (speed == 0) ? '0' : '1');
3080 
3081  LOGF_DEBUG("CMD (%s)", cmd);
3082 
3083  if (isSimulation())
3084  {
3085  strncpy(response, "M", 16);
3086  nbytes_read = strlen(response) + 1;
3087  }
3088  else
3089  {
3090  tcflush(PortFD, TCIFLUSH);
3091 
3092  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3093  {
3094  tty_error_msg(errcode, errmsg, MAXRBUF);
3095  LOGF_ERROR("%s", errmsg);
3096  return IPS_ALERT;
3097  }
3098 
3099  if (!isResponseOK())
3100  return IPS_ALERT;
3101 
3102  gettimeofday(&focusMoveStart, nullptr);
3103  focusMoveRequest = duration / 1000.0;
3104 
3105  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3106  {
3107  tty_error_msg(errcode, errmsg, MAXRBUF);
3108  LOGF_ERROR("%s", errmsg);
3109  return IPS_ALERT;
3110  }
3111  }
3112 
3113  if (nbytes_read > 0)
3114  {
3115  response[nbytes_read - 1] = '\0';
3116  LOGF_DEBUG("RES (%s)", response);
3117 
3118  if (duration <= getCurrentPollingPeriod())
3119  {
3120  usleep(getCurrentPollingPeriod() * 1000);
3121  AbortFocuser();
3122  return IPS_OK;
3123  }
3124 
3125  tcflush(PortFD, TCIFLUSH);
3126 
3127  return IPS_BUSY;
3128  }
3129 
3130  return IPS_ALERT;
3131 }
3132 
3133 /************************************************************************************
3134 *
3135 * ***********************************************************************************/
3137 {
3138  char cmd[LYNX_MAX] = {0};
3139  int errcode = 0;
3140  char errmsg[MAXRBUF];
3141  char response[LYNX_MAX] = {0};
3142  int nbytes_read = 0;
3143  int nbytes_written = 0;
3144 
3145  targetPosition = targetTicks;
3146 
3147  memset(response, 0, sizeof(response));
3148 
3149  snprintf(cmd, LYNX_MAX, "<%sMA%06d>", getFocusTarget(), targetTicks);
3150 
3151  LOGF_DEBUG("CMD (%s)", cmd);
3152 
3153  if (isSimulation())
3154  {
3155  strncpy(response, "M", 16);
3156  nbytes_read = strlen(response) + 1;
3157  simStatus[STATUS_MOVING] = ISS_ON;
3158  }
3159  else
3160  {
3161  tcflush(PortFD, TCIFLUSH);
3162 
3163  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3164  {
3165  tty_error_msg(errcode, errmsg, MAXRBUF);
3166  LOGF_ERROR("%s", errmsg);
3167  return IPS_ALERT;
3168  }
3169 
3170  if (!isResponseOK())
3171  return IPS_ALERT;
3172 
3173  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3174  {
3175  tty_error_msg(errcode, errmsg, MAXRBUF);
3176  LOGF_ERROR("%s", errmsg);
3177  return IPS_ALERT;
3178  }
3179  }
3180 
3181  if (nbytes_read > 0)
3182  {
3183  response[nbytes_read - 1] = '\0';
3184  LOGF_DEBUG("RES (%s)", response);
3185 
3187 
3188  tcflush(PortFD, TCIFLUSH);
3189 
3190  return IPS_BUSY;
3191  }
3192 
3193  return IPS_ALERT;
3194 }
3195 
3196 /************************************************************************************
3197 *
3198 * ***********************************************************************************/
3200 {
3201  uint32_t newPosition = 0;
3202 
3203  if (dir == FOCUS_INWARD)
3204  newPosition = FocusAbsPosN[0].value - ticks;
3205  else
3206  newPosition = FocusAbsPosN[0].value + ticks;
3207 
3208  return MoveAbsFocuser(newPosition);
3209 }
3210 
3211 /************************************************************************************
3212 *
3213 * ***********************************************************************************/
3215 {
3216  if (!isConnected())
3217  return;
3218 
3219  if (configurationComplete == false)
3220  {
3222  return;
3223  }
3224 
3225  bool statusrc = false;
3226  for (int i = 0; i < 2; i++)
3227  {
3228  statusrc = getFocusStatus();
3229  if (statusrc)
3230  break;
3231  }
3232 
3233  if (statusrc == false)
3234  {
3235  LOG_WARN("Unable to read focuser status....");
3237  return;
3238  }
3239 
3241  {
3242  if (isSimulation())
3243  {
3244  if (FocusAbsPosN[0].value < targetPosition)
3245  simPosition += 100;
3246  else
3247  simPosition -= 100;
3248 
3249  simStatus[STATUS_MOVING] = ISS_ON;
3250 
3251  if (std::abs(static_cast<int64_t>(simPosition) - static_cast<int64_t>(targetPosition)) < 100)
3252  {
3253  FocusAbsPosN[0].value = targetPosition;
3254  simPosition = FocusAbsPosN[0].value;
3255  simStatus[STATUS_MOVING] = ISS_OFF;
3256  StatusL[STATUS_MOVING].s = IPS_IDLE;
3257  if (simStatus[STATUS_HOMING] == ISS_ON)
3258  {
3259  StatusL[STATUS_HOMED].s = IPS_OK;
3260  StatusL[STATUS_HOMING].s = IPS_IDLE;
3261  simStatus[STATUS_HOMING] = ISS_OFF;
3262  simStatus[STATUS_HOMED] = ISS_ON;
3263  }
3264  }
3265  else
3266  StatusL[STATUS_MOVING].s = IPS_BUSY;
3267  IDSetLight(&StatusLP, nullptr);
3268  }
3269 
3270  if (isHoming && StatusL[STATUS_HOMED].s == IPS_OK)
3271  {
3272  isHoming = false;
3273  GotoSP.s = IPS_OK;
3274  IUResetSwitch(&GotoSP);
3275  GotoS[GOTO_HOME].s = ISS_ON;
3276  IDSetSwitch(&GotoSP, nullptr);
3278  IDSetNumber(&FocusRelPosNP, nullptr);
3279  LOG_INFO("Focuser completed home.");
3280  if (isSimulation())
3281  center();
3282  }
3283  else if (StatusL[STATUS_MOVING].s == IPS_IDLE)
3284  {
3287  IDSetNumber(&FocusAbsPosNP, nullptr);
3288  IDSetNumber(&FocusRelPosNP, nullptr);
3289  if (GotoSP.s == IPS_BUSY)
3290  {
3291  IUResetSwitch(&GotoSP);
3292  GotoSP.s = IPS_OK;
3293  IDSetSwitch(&GotoSP, nullptr);
3294  }
3295  LOG_INFO("Focuser reached requested position.");
3296  }
3297  else if (StatusL[STATUS_MOVING].s == IPS_BUSY && focusMoveRequest > 0)
3298  {
3299  float remaining = calcTimeLeft(focusMoveStart, focusMoveRequest);
3300 
3301  if (remaining < getCurrentPollingPeriod())
3302  {
3303  sleep(remaining);
3304  AbortFocuser();
3305  focusMoveRequest = 0;
3306  }
3307  }
3308  }
3309  if (StatusL[STATUS_HOMING].s == IPS_BUSY && GotoSP.s != IPS_BUSY)
3310  {
3311  GotoSP.s = IPS_BUSY;
3312  IDSetSwitch(&GotoSP, nullptr);
3313  }
3314 
3316 }
3317 
3318 /************************************************************************************
3319  *
3320 * ***********************************************************************************/
3322 {
3323  char cmd[LYNX_MAX] = {0};
3324  int errcode = 0;
3325  char errmsg[MAXRBUF];
3326  char response[LYNX_MAX] = {0};
3327  int nbytes_read = 0;
3328  int nbytes_written = 0;
3329 
3330  memset(response, 0, sizeof(response));
3331  snprintf(cmd, LYNX_MAX, "<%sHALT>", getFocusTarget());
3332  LOGF_DEBUG("CMD (%s)", cmd);
3333 
3334  if (isSimulation())
3335  {
3336  strncpy(response, "HALTED", 16);
3337  nbytes_read = strlen(response) + 1;
3338  simStatus[STATUS_MOVING] = ISS_OFF;
3339  simStatus[STATUS_HOMING] = ISS_OFF;
3340  }
3341  else
3342  {
3343  tcflush(PortFD, TCIFLUSH);
3344 
3345  if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3346  {
3347  tty_error_msg(errcode, errmsg, MAXRBUF);
3348  LOGF_ERROR("%s", errmsg);
3349  return false;
3350  }
3351 
3352  if (!isResponseOK())
3353  return false;
3354 
3355  if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3356  {
3357  tty_error_msg(errcode, errmsg, MAXRBUF);
3358  LOGF_ERROR("%s", errmsg);
3359  return false;
3360  }
3361  }
3362 
3363  if (nbytes_read > 0)
3364  {
3365  response[nbytes_read - 1] = '\0';
3366  LOGF_DEBUG("RES (%s)", response);
3367 
3368  if (FocusRelPosNP.s == IPS_BUSY)
3369  {
3371  IDSetNumber(&FocusRelPosNP, nullptr);
3372  }
3373 
3376  GotoSP.s = IPS_IDLE;
3377  IUResetSwitch(&GotoSP);
3378  IDSetNumber(&FocusTimerNP, nullptr);
3379  IDSetNumber(&FocusAbsPosNP, nullptr);
3380  IDSetSwitch(&GotoSP, nullptr);
3381 
3382  tcflush(PortFD, TCIFLUSH);
3383 
3384  return true;
3385  }
3386 
3387  return false;
3388 }
3389 
3390 /************************************************************************************
3391  *
3392 * ***********************************************************************************/
3393 float FocusLynxBase::calcTimeLeft(timeval start, float req)
3394 {
3395  double timesince;
3396  double timeleft;
3397  struct timeval now
3398  {
3399  0, 0
3400  };
3401  gettimeofday(&now, nullptr);
3402 
3403  timesince =
3404  static_cast<int>((now.tv_sec * 1000.0 + now.tv_usec / 1000)) - static_cast<int>((start.tv_sec * 1000.0 + start.tv_usec /
3405  1000));
3406  timesince = timesince / 1000;
3407  timeleft = req - timesince;
3408  return timeleft;
3409 }
3410 
3411 /************************************************************************************
3412  *
3413 * ***********************************************************************************/
3415 {
3417 
3419  IUSaveConfigSwitch(fp, &TemperatureCompensateSP);
3420  IUSaveConfigSwitch(fp, &TemperatureCompensateOnStartSP);
3421  //IUSaveConfigSwitch(fp, &ReverseSP);
3422  IUSaveConfigNumber(fp, &TemperatureNP);
3423  IUSaveConfigSwitch(fp, &TemperatureCompensateModeSP);
3424  //IUSaveConfigSwitch(fp, &FocusBacklashSP);
3425  //IUSaveConfigNumber(fp, &FocusBacklashNP);
3426  IUSaveConfigNumber(fp, &StepSizeNP);
3427 
3428  return true;
3429 }
3430 
3431 /************************************************************************************
3432 *
3433 ************************************************************************************/
3434 bool FocusLynxBase::loadConfig(bool silent, const char *property)
3435 {
3436  bool result = true;
3437 
3438  if (property == nullptr)
3439  {
3440  // Need to know the user choice for this option not store in HUB
3441  result = INDI::DefaultDevice::loadConfig(silent, "Presets") && result;
3442  if (isSimulation())
3443  {
3444  // Only load for simulation, otherwise got from the HUB
3445  result = (INDI::DefaultDevice::loadConfig(silent, "MODEL") && result);
3446  result = (INDI::DefaultDevice::loadConfig(silent, "T. COMPENSATION") && result);
3447  result = (INDI::DefaultDevice::loadConfig(silent, "T. COMPENSATION @START") && result);
3448  result = (INDI::DefaultDevice::loadConfig(silent, "REVERSE") && result);
3449  result = (INDI::DefaultDevice::loadConfig(silent, "T. COEFF") && result);
3450  result = (INDI::DefaultDevice::loadConfig(silent, "COMPENSATE MODE") && result);
3451  // result = (INDI::DefaultDevice::loadConfig(silent, "BACKLASH COMPENSATION") && result);
3452  // result = (INDI::DefaultDevice::loadConfig(silent, "BACKLASH") && result);
3453  result = (INDI::DefaultDevice::loadConfig(silent, "MAX TRAVEL") && result);
3454  result = (INDI::DefaultDevice::loadConfig(silent, "STEP SIZE") && result);
3455  result = (INDI::DefaultDevice::loadConfig(silent, "T. PARAMETERS") && result);
3456  }
3457  }
3458  else
3459  result = INDI::DefaultDevice::loadConfig(silent, property);
3460 
3461  return result;
3462 }
3463 
3464 /************************************************************************************
3465  *
3466 * ***********************************************************************************/
3468 {
3469  INDI_UNUSED(enable);
3470  //tty_set_debug(enable ? 1 : 0);
3471 }
3472 
3473 /************************************************************************************
3474  *
3475 * ***********************************************************************************/
3476 void FocusLynxBase::setFocusTarget(const char *target)
3477 // Use to set the string of the private char[] focusTarget
3478 {
3479  strncpy(focusTarget, target, 8);
3480 }
3481 
3482 /************************************************************************************
3483  *
3484 * ***********************************************************************************/
3486 // Use to get the string of the private char[] focusTarget
3487 {
3488  return focusTarget;
3489 }
3490 
3491 /************************************************************************************
3492  *
3493 * ***********************************************************************************/
3494 int FocusLynxBase::getVersion(int *major, int *minor, int *sub)
3495 {
3496  INDI_UNUSED(major);
3497  INDI_UNUSED(minor);
3498  INDI_UNUSED(sub);
3499  /* For future use of implementation of new firmware 2.0.0
3500  * and give ability to keep compatible to actual 1.0.9
3501  * Will be to avoid calling to new functions
3502  * Not yet implemented in this version of the driver
3503  */
3504  char sMajor[8], sMinor[8], sSub[8];
3505  int rc = sscanf(version, "%[^.].%[^.].%s", sMajor, sMinor, sSub);
3506 
3507  LOGF_DEBUG("Version major: %s, minor: %s, subversion: %s", sMajor, sMinor, sSub);
3508  *major = atoi(sMajor);
3509  *minor = atoi(sMinor);
3510  *sub = atoi(sSub);
3511  if (rc == 3)
3512  return *major;
3513  return 0; // 0 Means error in this case
3514 }
INDI::FocuserInterface::FOCUSER_CAN_ABS_MOVE
@ FOCUSER_CAN_ABS_MOVE
Definition: indifocuserinterface.h:74
FocusLynxBase::STATUS_HNDCTRL
@ STATUS_HNDCTRL
Definition: focuslynxbase.h:73
FocusLynxBase::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: focuslynxbase.cpp:334
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::FocuserInterface::FOCUSER_CAN_SYNC
@ FOCUSER_CAN_SYNC
Definition: indifocuserinterface.h:78
SUBVERSION
#define SUBVERSION
Definition: ifwoptec.h:24
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
FocusLynxBase::getFocusTarget
const char * getFocusTarget()
Definition: focuslynxbase.cpp:3485
INDI::FocuserInterface::FocusAbsPosNP
INumberVectorProperty FocusAbsPosNP
Definition: indifocuserinterface.h:282
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
INDI::DefaultDevice::addAuxControls
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Definition: defaultdevice.cpp:665
INDI::FocuserInterface::FocusMaxPosNP
INumberVectorProperty FocusMaxPosNP
Definition: indifocuserinterface.h:290
IUUpdateMinMax
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
Definition: indidriver.c:1850
IPState
IPState
Property state.
Definition: indiapi.h:158
FocusLynxBase::ISGetProperties
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: focuslynxbase.cpp:222
INDI::FocuserInterface::FocusBacklashN
INumber FocusBacklashN[1]
Definition: indifocuserinterface.h:311
FocusLynxBase::Handshake
virtual bool Handshake() override
perform handshake with device to check communication
Definition: focuslynxbase.cpp:309
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
INDI::FocuserInterface::FocusSyncNP
INumberVectorProperty FocusSyncNP
Definition: indifocuserinterface.h:294
FocusLynxBase::MoveAbsFocuser
virtual IPState MoveAbsFocuser(uint32_t targetPosition) override
MoveFocuser the focuser to an absolute position.
Definition: focuslynxbase.cpp:3136
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
ISwitch
One switch descriptor.
FocusLynxBase::TimerHit
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: focuslynxbase.cpp:3214
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
INDI::Focuser::ISGetProperties
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: indifocuser.cpp:111
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
FocusLynxBase::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: focuslynxbase.cpp:116
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INDI::DefaultDevice::isSimulation
bool isSimulation() const
Definition: defaultdevice.cpp:734
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
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
FocusLynxBase::LedN
INumber LedN[1]
Definition: focuslynxbase.h:130
FocusLynxBase::version
char version[16]
Definition: focuslynxbase.h:134
IUFillTextVector
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: indidriver.c:477
INDI::Focuser::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: indifocuser.cpp:222
INDI_UNUSED
#define INDI_UNUSED(x)
Definition: indidevapi.h:799
FocusLynxBase::LedNP
INumberVectorProperty LedNP
Definition: focuslynxbase.h:131
FocusLynxBase::SetFocuserMaxPosition
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
Definition: focuslynxbase.cpp:2825
FocusLynxBase::loadConfig
virtual bool loadConfig(bool silent, const char *property) override
Load the last saved configuration file.
Definition: focuslynxbase.cpp:3434
INDI::Focuser::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: indifocuser.cpp:241
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
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
_ILightVectorProperty::s
IPState s
Definition: indiapi.h:426
FocusLynxBase::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: focuslynxbase.cpp:3414
IUFillLight
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.
Definition: indidriver.c:334
tty_read_section
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:557
INDI::FocuserInterface::FOCUSER_CAN_ABORT
@ FOCUSER_CAN_ABORT
Definition: indifocuserinterface.h:76
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1455
IUFillText
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: indidriver.c:369
INDI::FocuserInterface::FocusReverseSP
ISwitchVectorProperty FocusReverseSP
Definition: indifocuserinterface.h:302
IUUpdateText
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:259
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
FocusLynxBase::getVersion
virtual int getVersion(int *major, int *minor, int *sub)
Definition: focuslynxbase.cpp:3494
FocusLynxBase::ReverseFocuser
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition: focuslynxbase.cpp:2703
FocusLynxBase::STATUS_REMOTEIO
@ STATUS_REMOTEIO
Definition: focuslynxbase.h:72
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1442
_ILightVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:420
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:1156
FOCUS_STATUS_TAB
#define FOCUS_STATUS_TAB
Definition: focuslynxbase.h:44
FocusLynxBase::STATUS_REVERSE
@ STATUS_REVERSE
Definition: focuslynxbase.h:74
IUFindOnSwitch
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *sp)
Returns the first ON switch it finds in the vector switch property.
Definition: indicom.c:1414
INDI::Focuser::SyncPresets
virtual void SyncPresets(uint32_t ticks)
syncPresets Updates the min/max/step range of the preset as per the maximum name of Absolute Focus Tr...
Definition: indifocuser.cpp:392
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
INDI::FocuserInterface::FocusBacklashSP
ISwitchVectorProperty FocusBacklashSP
Definition: indifocuserinterface.h:306
FocusLynxBase::SyncFocuser
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
Definition: focuslynxbase.cpp:2762
FocusLynxBase::MoveFocuser
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser the focuser in a particular direction with a specific speed for a finite duration.
Definition: focuslynxbase.cpp:3068
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
FocusLynxBase::SetFocuserBacklashEnabled
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
Definition: focuslynxbase.cpp:2586
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
FocusLynxBase::setFocusTarget
void setFocusTarget(const char *target)
Definition: focuslynxbase.cpp:3476
_ISwitchVectorProperty::nsp
int nsp
Definition: indiapi.h:386
IDSetLight
void void void void void void void IDSetLight(const ILightVectorProperty *l, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing light vector property.
INDI::FocuserInterface::FocusTimerNP
INumberVectorProperty FocusTimerNP
Definition: indifocuserinterface.h:278
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
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
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
focuslynxbase.h
FocusLynxBase::STATUS_HOMED
@ STATUS_HOMED
Definition: focuslynxbase.h:69
FocusLynxBase::STATUS_MOVING
@ STATUS_MOVING
Definition: focuslynxbase.h:67
INDI::FocuserInterface::FocusRelPosN
INumber FocusRelPosN[1]
Definition: indifocuserinterface.h:287
FocusLynxBase::debugTriggered
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
Definition: focuslynxbase.cpp:3467
FocusLynxBase::ModelS
ISwitch * ModelS
Definition: focuslynxbase.h:126
FocusLynxBase::SetFocuserBacklash
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
Definition: focuslynxbase.cpp:2645
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
INDI::DefaultDevice::loadConfig
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
Definition: defaultdevice.cpp:147
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
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
FocusLynxBase::STATUS_HOMING
@ STATUS_HOMING
Definition: focuslynxbase.h:68
FocusLynxBase::setDeviceType
bool setDeviceType(int index)
Definition: focuslynxbase.cpp:1968
FocusLynxBase::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: focuslynxbase.cpp:519
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
INDI::FocuserInterface::FocusBacklashS
ISwitch FocusBacklashS[2]
Definition: indifocuserinterface.h:307
FocusLynxBase::getDefaultName
virtual const char * getDefaultName() override
Definition: focuslynxbase.cpp:325
FocusLynxBase::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: focuslynxbase.cpp:497
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
VERSION
#define VERSION
Definition: ifwoptec.h:23
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
FocusLynxBase::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: focuslynxbase.cpp:237
IUSaveText
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indicom.c:1449
name
const char * name
Definition: indiserver.c:116
_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
FocusLynxBase::GOTO_HOME
@ GOTO_HOME
Definition: focuslynxbase.h:80
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
LYNXFOCUS_TIMEOUT
#define LYNXFOCUS_TIMEOUT
Definition: focuslynxbase.h:38
_INumberVectorProperty::p
IPerm p
Definition: indiapi.h:328
FocusLynxBase::GOTO_CENTER
@ GOTO_CENTER
Definition: focuslynxbase.h:79
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
FocusLynxBase::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: focuslynxbase.cpp:3199
FocusLynxBase::FocusLynxBase
FocusLynxBase()
Definition: focuslynxbase.cpp:33
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
FocusLynxBase::AbortFocuser
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: focuslynxbase.cpp:3321
INDI::FocuserInterface::FOCUSER_HAS_BACKLASH
@ FOCUSER_HAS_BACKLASH
Definition: indifocuserinterface.h:80
ISState
ISState
Switch state.
Definition: indiapi.h:148
FOCUS_SETTINGS_TAB
#define FOCUS_SETTINGS_TAB
Definition: dmfc.cpp:34
FocusLynxBase::isResponseOK
bool isResponseOK()
Definition: focuslynxbase.cpp:3013
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1424
FocusLynxBase::configurationComplete
bool configurationComplete
Definition: focuslynxbase.h:123
FocusLynxBase::ack
bool ack()
Definition: focuslynxbase.cpp:641
INDI::FocuserInterface::FocusSyncN
INumber FocusSyncN[1]
Definition: indifocuserinterface.h:295
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
INDI::Focuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:58
FocusLynxBase::STATUS_TMPPROBE
@ STATUS_TMPPROBE
Definition: focuslynxbase.h:71
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:465
TTY_OK
@ TTY_OK
Definition: indicom.h:94
INDI::FocuserInterface::FocusBacklashNP
INumberVectorProperty FocusBacklashNP
Definition: indifocuserinterface.h:310
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
IUFillLightVector
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.
Definition: indidriver.c:435
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.
FocusLynxBase::STATUS_FFDETECT
@ STATUS_FFDETECT
Definition: focuslynxbase.h:70
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
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
Aux::buffer
std::vector< uint8_t > buffer
Definition: celestronauxpacket.h:38
FocusLynxBase::ModelSP
ISwitchVectorProperty ModelSP
Definition: focuslynxbase.h:127
INDI::BaseDevice::INDI_DISABLED
@ INDI_DISABLED
Definition: basedevice.h:65
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151