Instrument Neutral Distributed Interface INDI 2.2.5
focuslynxbase.cpp
Go to the documentation of this file.
1/*
2 Focus Lynx INDI driver
3 Copyright (C) 2015 Jasem Mutlaq ([email protected])
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* ***********************************************************************************/
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 // Although 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 }
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 = FocusAbsPosNP[0].getValue();
213
215
216 return true;
217}
218
219/************************************************************************************
220 *
221* ***********************************************************************************/
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 overridden by child instance
328 return "FocusLynxBase";
329}
330
331/************************************************************************************
332 *
333* ***********************************************************************************/
334bool 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 // FocusBacklashSP.apply();
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* ***********************************************************************************/
497bool 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* ***********************************************************************************/
519bool 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(FocusBacklashNP.apply();) == 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 // FocusAbsPosNP[0].setMax(SyncNP[0].setMax(MaxTravelN[0].value));
608 // FocusAbsPosNP[0].setStep(SyncNP[0].setStep((MaxTravelN[0].value / 50.0)));
609
610 // FocusAbsPosNP.updateMinMax();
611 // IUUpdateMinMax(&SyncNP);
612
613 // IDSetNumber(&MaxTravelNP, nullptr);
614
615 // LOGF_INFO("Focuser absolute limits: min (%g) max (%g)", FocusAbsPosNP[0].getMin(),
616 // FocusAbsPosNP[0].getMax());
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 snprintf(response, LYNX_MAX, "%s", focusName);
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* ***********************************************************************************/
696bool 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, "%15[^=]=%15[^\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, "%15[^=]=%d", key, &maxPos);
797 if (rc == 2)
798 {
799 FocusAbsPosNP[0].setMin(0);
800 FocusAbsPosNP[0].setMax(maxPos);
801 FocusAbsPosNP[0].setStep(maxPos / 50.0);
802
803 FocusSyncNP[0].setMin(0);
804 FocusSyncNP[0].setMax(maxPos);
805 FocusSyncNP[0].setStep(maxPos / 50.0);
806
807 FocusRelPosNP[0].setMin(0);
808 FocusRelPosNP[0].setMax(maxPos / 2);
809 FocusRelPosNP[0].setStep(maxPos / 100.0);
810
814
816 FocusMaxPosNP[0].setValue(maxPos);
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 through 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", FocusBacklashSP[INDI_ENABLED].getState() == 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, "%15[^=]=%d", key, &BLCCompensate);
976 if (rc != 2)
977 return false;
978
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, "%15[^=]=%d", key, &BLCValue);
1003 if (rc != 2)
1004 return false;
1005
1006 FocusBacklashNP[0].setValue(BLCValue);
1009
1010 // Led brightness
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, "%15[^=]=%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, "%15[^=]=%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 complete 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* ***********************************************************************************/
1102bool 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, "%15[^=]=%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, "%15[^=]=%d", key, &currPos);
1213 if (rc == 2)
1214 {
1215 FocusAbsPosNP[0].setValue(currPos);
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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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, "%15[^=]=%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 && FocusReverseSP[INDI_DISABLED].getState() == ISS_ON) || (!reverse
1436 && FocusReverseSP[INDI_ENABLED].getState() == ISS_ON))
1437 {
1439 FocusReverseSP[INDI_ENABLED].setState((reverse == 1) ? ISS_ON : ISS_OFF);
1440 FocusReverseSP[INDI_DISABLED].setState((reverse == 0) ? ISS_ON : ISS_OFF);
1442 }
1443
1444 StatusLP.s = IPS_OK;
1445 IDSetLight(&StatusLP, nullptr);
1446
1447 // END is reached
1448 memset(response, 0, sizeof(response));
1449 if (isSimulation())
1450 {
1451 strncpy(response, "END\n", 16);
1452 nbytes_read = strlen(response);
1453 }
1454 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1455 {
1456 tty_error_msg(errcode, errmsg, MAXRBUF);
1457 LOGF_ERROR("%s", errmsg);
1458 return false;
1459 }
1460
1461 if (nbytes_read > 0)
1462 {
1463 response[nbytes_read - 1] = '\0';
1464
1465 // Display the response to be sure to have read the complete TTY Buffer.
1466 LOGF_DEBUG("RES (%s)", response);
1467 if (strcmp(response, "END"))
1468 return false;
1469 }
1470
1471 tcflush(PortFD, TCIFLUSH);
1472
1473 return true;
1474 }
1475 return false;
1476}
1477
1478/************************************************************************************
1479 *
1480* ***********************************************************************************/
1481bool FocusLynxBase::getFocusTemp()
1482{
1483 // Get value related to Temperature compensation
1484
1485 char cmd[LYNX_MAX] = {0};
1486 int errcode = 0;
1487 char errmsg[MAXRBUF];
1488 char response[LYNX_MAX] = {0};
1489 int nbytes_read = 0;
1490 int nbytes_written = 0;
1491 char key[16];
1492
1493 memset(response, 0, sizeof(response));
1494
1495 snprintf(cmd, LYNX_MAX, "<%sGETTCI>", getFocusTarget());
1496 LOGF_DEBUG("CMD (%s)", cmd);
1497
1498 if (isSimulation())
1499 {
1500 if (!strcmp(getFocusTarget(), "F1"))
1501 strncpy(response, "TEMP COMP1", 16);
1502 else
1503 strncpy(response, "TEMP COMP2", 16);
1504 nbytes_read = strlen(response) + 1;
1505 }
1506 else
1507 {
1508 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1509 {
1510 tty_error_msg(errcode, errmsg, MAXRBUF);
1511 LOGF_ERROR("%s", errmsg);
1512 return false;
1513 }
1514
1515 if (!isResponseOK())
1516 return false;
1517
1518 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1519 {
1520 tty_error_msg(errcode, errmsg, MAXRBUF);
1521 LOGF_ERROR("%s", errmsg);
1522 return false;
1523 }
1524 }
1525
1526 if (nbytes_read > 0)
1527 {
1528 response[nbytes_read - 1] = '\0';
1529 LOGF_DEBUG("RES (%s)", response);
1530
1531 if ((strcmp(response, "TEMP COMP1")) && (strcmp(response, "TEMP COMP2")))
1532 return false;
1533
1534 memset(response, 0, sizeof(response));
1535
1536 // Temperature Compensation On?
1537 if (isSimulation())
1538 {
1539 snprintf(response, 32, "TComp ON = %d\n", TemperatureCompensateS[0].s == ISS_ON ? 1 : 0);
1540 nbytes_read = strlen(response);
1541 }
1542 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1543 {
1544 tty_error_msg(errcode, errmsg, MAXRBUF);
1545 LOGF_ERROR("%s", errmsg);
1546 return false;
1547 }
1548 response[nbytes_read - 1] = '\0';
1549 LOGF_DEBUG("RES (%s)", response);
1550
1551 int TCompOn;
1552 int rc = sscanf(response, "%15[^=]=%d", key, &TCompOn);
1553 if (rc != 2)
1554 return false;
1555
1556 IUResetSwitch(&TemperatureCompensateSP);
1557 TemperatureCompensateS[0].s = TCompOn ? ISS_ON : ISS_OFF;
1558 TemperatureCompensateS[1].s = TCompOn ? ISS_OFF : ISS_ON;
1559 TemperatureCompensateSP.s = IPS_OK;
1560 IDSetSwitch(&TemperatureCompensateSP, nullptr);
1561
1562 memset(response, 0, sizeof(response));
1563
1564 // Temperature Compensation Mode
1565 if (isSimulation())
1566 {
1567 snprintf(response, 32, "TC Mode = %c\n", 'C');
1568 nbytes_read = strlen(response);
1569 }
1570 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1571 {
1572 tty_error_msg(errcode, errmsg, MAXRBUF);
1573 LOGF_ERROR("%s", errmsg);
1574 return false;
1575 }
1576 response[nbytes_read - 1] = '\0';
1577 LOGF_DEBUG("RES (%s)", response);
1578
1579 char compensateMode;
1580 rc = sscanf(response, "%15[^=]= %c", key, &compensateMode);
1581 if (rc != 2)
1582 {
1583 if (rc == 1 && key[0] == 'T')
1584 {
1585 //If the controller does not support this it could be null. Assume A mode in this case.
1586 compensateMode = 'A';
1587 }
1588 else
1589 {
1590 return false;
1591 }
1592 }
1593
1594 IUResetSwitch(&TemperatureCompensateModeSP);
1595 int index = compensateMode - 'A';
1596 if (index >= 0 && index <= 5)
1597 {
1598 TemperatureCompensateModeS[index].s = ISS_ON;
1599 TemperatureCompensateModeSP.s = IPS_OK;
1600 }
1601 else
1602 {
1603 LOGF_ERROR("Invalid index %d for compensation mode.", index);
1604 TemperatureCompensateModeSP.s = IPS_ALERT;
1605 }
1606
1607 IDSetSwitch(&TemperatureCompensateModeSP, nullptr);
1608
1609
1610 // Temperature Compensation on Start
1611 memset(response, 0, sizeof(response));
1612 if (isSimulation())
1613 {
1614 snprintf(response, 32, "TC@Start = %d\n", TemperatureCompensateOnStartS[0].s == ISS_ON ? 1 : 0);
1615 nbytes_read = strlen(response);
1616 }
1617 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1618 {
1619 tty_error_msg(errcode, errmsg, MAXRBUF);
1620 LOGF_ERROR("%s", errmsg);
1621 return false;
1622 }
1623 response[nbytes_read - 1] = '\0';
1624 LOGF_DEBUG("RES (%s)", response);
1625
1626 int TCOnStart;
1627 rc = sscanf(response, "%15[^=]=%d", key, &TCOnStart);
1628 if (rc != 2)
1629 return false;
1630
1631 IUResetSwitch(&TemperatureCompensateOnStartSP);
1632 TemperatureCompensateOnStartS[0].s = TCOnStart ? ISS_ON : ISS_OFF;
1633 TemperatureCompensateOnStartS[1].s = TCOnStart ? ISS_OFF : ISS_ON;
1634 TemperatureCompensateOnStartSP.s = IPS_OK;
1635 IDSetSwitch(&TemperatureCompensateOnStartSP, nullptr);
1636
1637 // Temperature Coeff A
1638 if (isSimulation())
1639 {
1640 snprintf(response, 32, "TempCo A = %d\n", static_cast<int>(TemperatureParamN[0].value));
1641 nbytes_read = strlen(response);
1642 }
1643 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1644 {
1645 tty_error_msg(errcode, errmsg, MAXRBUF);
1646 LOGF_ERROR("%s", errmsg);
1647 return false;
1648 }
1649
1650 if (TemperatureCompensateModeS[0].s == ISS_ON)
1651 {
1652 response[nbytes_read - 1] = '\0';
1653 LOGF_DEBUG("RES (%s)", response);
1654
1655 int TCoeff;
1656 rc = sscanf(response, "%15[^=]=%d", key, &TCoeff);
1657 if (rc != 2)
1658 return false;
1659
1660 TemperatureParamN[0].value = TCoeff;
1661 }
1662 memset(response, 0, sizeof(response));
1663
1664 // Temperature Coeff B
1665 if (isSimulation())
1666 {
1667 snprintf(response, 32, "TempCo B = %d\n", static_cast<int>(TemperatureParamN[0].value));
1668 nbytes_read = strlen(response);
1669 }
1670 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1671 {
1672 tty_error_msg(errcode, errmsg, MAXRBUF);
1673 LOGF_ERROR("%s", errmsg);
1674 return false;
1675 }
1676 if (TemperatureCompensateModeS[1].s == ISS_ON)
1677 {
1678 response[nbytes_read - 1] = '\0';
1679 LOGF_DEBUG("RES (%s)", response);
1680
1681 int TCoeff;
1682 rc = sscanf(response, "%15[^=]=%d", key, &TCoeff);
1683 if (rc != 2)
1684 return false;
1685
1686 TemperatureParamN[0].value = TCoeff;
1687 }
1688
1689 memset(response, 0, sizeof(response));
1690
1691 // Temperature Coeff C
1692 if (isSimulation())
1693 {
1694 snprintf(response, 32, "TempCo C = %d\n", static_cast<int>(TemperatureParamN[0].value));
1695 nbytes_read = strlen(response);
1696 }
1697 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1698 {
1699 tty_error_msg(errcode, errmsg, MAXRBUF);
1700 LOGF_ERROR("%s", errmsg);
1701 return false;
1702 }
1703 if (TemperatureCompensateModeS[2].s == ISS_ON)
1704 {
1705 response[nbytes_read - 1] = '\0';
1706 LOGF_DEBUG("RES (%s)", response);
1707
1708 int TCoeff;
1709 rc = sscanf(response, "%15[^=]=%d", key, &TCoeff);
1710 if (rc != 2)
1711 return false;
1712
1713 TemperatureParamN[0].value = TCoeff;
1714 }
1715
1716 memset(response, 0, sizeof(response));
1717
1718 // Temperature Coeff D
1719 if (isSimulation())
1720 {
1721 snprintf(response, 32, "TempCo D = %d\n", static_cast<int>(TemperatureParamN[0].value));
1722 nbytes_read = strlen(response);
1723 }
1724 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1725 {
1726 tty_error_msg(errcode, errmsg, MAXRBUF);
1727 LOGF_ERROR("%s", errmsg);
1728 return false;
1729 }
1730 if (TemperatureCompensateModeS[3].s == ISS_ON)
1731 {
1732 response[nbytes_read - 1] = '\0';
1733 LOGF_DEBUG("RES (%s)", response);
1734
1735 int TCoeff;
1736 rc = sscanf(response, "%15[^=]=%d", key, &TCoeff);
1737 if (rc != 2)
1738 return false;
1739
1740 TemperatureParamN[0].value = TCoeff;
1741 }
1742
1743 memset(response, 0, sizeof(response));
1744
1745 // Temperature Coeff E
1746 if (isSimulation())
1747 {
1748 snprintf(response, 32, "TempCo E = %d\n", static_cast<int>(TemperatureParamN[0].value));
1749 nbytes_read = strlen(response);
1750 }
1751 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1752 {
1753 tty_error_msg(errcode, errmsg, MAXRBUF);
1754 LOGF_ERROR("%s", errmsg);
1755 return false;
1756 }
1757 if (TemperatureCompensateModeS[4].s == ISS_ON)
1758 {
1759 response[nbytes_read - 1] = '\0';
1760 LOGF_DEBUG("RES (%s)", response);
1761
1762 int TCoeff;
1763 rc = sscanf(response, "%15[^=]=%d", key, &TCoeff);
1764 if (rc != 2)
1765 return false;
1766
1767 TemperatureParamN[0].value = TCoeff;
1768 }
1769
1770 memset(response, 0, sizeof(response));
1771
1772 // Temperature intercepts A
1773 if (isSimulation())
1774 {
1775 snprintf(response, 32, "TempIn A = %d\n", static_cast<int>(TemperatureParamN[1].value));
1776 nbytes_read = strlen(response);
1777 }
1778 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1779 {
1780 tty_error_msg(errcode, errmsg, MAXRBUF);
1781 LOGF_ERROR("%s", errmsg);
1782 return false;
1783 }
1784 if (TemperatureCompensateModeS[0].s == ISS_ON)
1785 {
1786 response[nbytes_read - 1] = '\0';
1787 LOGF_DEBUG("RES (%s)", response);
1788
1789 int TInter;
1790 rc = sscanf(response, "%15[^=]=%d", key, &TInter);
1791 if (rc != 2)
1792 return false;
1793
1794 TemperatureParamN[1].value = TInter;
1795 }
1796
1797 memset(response, 0, sizeof(response));
1798
1799 // Temperature intercepts B
1800 if (isSimulation())
1801 {
1802 snprintf(response, 32, "TempIn B = %d\n", static_cast<int>(TemperatureParamN[1].value));
1803 nbytes_read = strlen(response);
1804 }
1805 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1806 {
1807 tty_error_msg(errcode, errmsg, MAXRBUF);
1808 LOGF_ERROR("%s", errmsg);
1809 return false;
1810 }
1811 if (TemperatureCompensateModeS[1].s == ISS_ON)
1812 {
1813 response[nbytes_read - 1] = '\0';
1814 LOGF_DEBUG("RES (%s)", response);
1815
1816 int TInter;
1817 rc = sscanf(response, "%15[^=]=%d", key, &TInter);
1818 if (rc != 2)
1819 return false;
1820
1821 TemperatureParamN[1].value = TInter;
1822 }
1823
1824 memset(response, 0, sizeof(response));
1825
1826 // Temperature intercepts C
1827 if (isSimulation())
1828 {
1829 snprintf(response, 32, "TempIn C = %d\n", static_cast<int>(TemperatureParamN[1].value));
1830 nbytes_read = strlen(response);
1831 }
1832 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1833 {
1834 tty_error_msg(errcode, errmsg, MAXRBUF);
1835 LOGF_ERROR("%s", errmsg);
1836 return false;
1837 }
1838 if (TemperatureCompensateModeS[2].s == ISS_ON)
1839 {
1840 response[nbytes_read - 1] = '\0';
1841 LOGF_DEBUG("RES (%s)", response);
1842
1843 int TInter;
1844 rc = sscanf(response, "%15[^=]=%d", key, &TInter);
1845 if (rc != 2)
1846 return false;
1847
1848 TemperatureParamN[1].value = TInter;
1849 }
1850
1851 memset(response, 0, sizeof(response));
1852
1853 // Temperature intercepts D
1854 if (isSimulation())
1855 {
1856 snprintf(response, 32, "TempIn D = %d\n", static_cast<int>(TemperatureParamN[1].value));
1857 nbytes_read = strlen(response);
1858 }
1859 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1860 {
1861 tty_error_msg(errcode, errmsg, MAXRBUF);
1862 LOGF_ERROR("%s", errmsg);
1863 return false;
1864 }
1865 if (TemperatureCompensateModeS[3].s == ISS_ON)
1866 {
1867 response[nbytes_read - 1] = '\0';
1868 LOGF_DEBUG("RES (%s)", response);
1869
1870 int TInter;
1871 rc = sscanf(response, "%15[^=]=%d", key, &TInter);
1872 if (rc != 2)
1873 return false;
1874
1875 TemperatureParamN[1].value = TInter;
1876 }
1877
1878 memset(response, 0, sizeof(response));
1879
1880 // Temperature intercepts E
1881 if (isSimulation())
1882 {
1883 snprintf(response, 32, "TempIn E = %d\n", static_cast<int>(TemperatureParamN[1].value));
1884 nbytes_read = strlen(response);
1885 }
1886 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1887 {
1888 tty_error_msg(errcode, errmsg, MAXRBUF);
1889 LOGF_ERROR("%s", errmsg);
1890 return false;
1891 }
1892 if (TemperatureCompensateModeS[4].s == ISS_ON)
1893 {
1894 response[nbytes_read - 1] = '\0';
1895 LOGF_DEBUG("RES (%s)", response);
1896
1897 int TInter;
1898 rc = sscanf(response, "%15[^=]=%d", key, &TInter);
1899 if (rc != 2)
1900 return false;
1901
1902 TemperatureParamN[1].value = TInter;
1903 }
1904
1905 TemperatureParamNP.s = IPS_OK;
1906 IDSetNumber(&TemperatureParamNP, nullptr);
1907
1908 memset(response, 0, sizeof(response));
1909
1910 // StepSize
1911 if (isSimulation())
1912 {
1913 snprintf(response, 32, "StepSize = %d\n", static_cast<int>(StepSizeN[0].value));
1914 nbytes_read = strlen(response);
1915 }
1916 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1917 {
1918 tty_error_msg(errcode, errmsg, MAXRBUF);
1919 LOGF_ERROR("%s", errmsg);
1920 return false;
1921 }
1922 response[nbytes_read - 1] = '\0';
1923 LOGF_DEBUG("RES (%s)", response);
1924
1925 int valueStepSize;
1926 rc = sscanf(response, "%15[^=]=%d", key, &valueStepSize);
1927 if (rc != 2)
1928 return false;
1929
1930 StepSizeN[0].value = valueStepSize;
1931 IDSetNumber(&StepSizeNP, nullptr);
1932
1933 memset(response, 0, sizeof(response));
1934
1935 // END is reached
1936 memset(response, 0, sizeof(response));
1937 if (isSimulation())
1938 {
1939 strncpy(response, "END\n", 16);
1940 nbytes_read = strlen(response);
1941 }
1942 else if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
1943 {
1944 tty_error_msg(errcode, errmsg, MAXRBUF);
1945 LOGF_ERROR("%s", errmsg);
1946 return false;
1947 }
1948
1949 if (nbytes_read > 0)
1950 {
1951 response[nbytes_read - 1] = '\0';
1952
1953 // Display the response to be sure to have read the complete TTY Buffer.
1954 LOGF_DEBUG("RES (%s)", response);
1955 if (strcmp(response, "END"))
1956 return false;
1957 }
1958
1959 tcflush(PortFD, TCIFLUSH);
1960
1961 return true;
1962 }
1963 return false;
1964}
1965
1966/************************************************************************************
1967 *
1968* ***********************************************************************************/
1970{
1971 char cmd[16];
1972 int errcode = 0;
1973 char errmsg[MAXRBUF];
1974 char response[LYNX_MAX] = {0};
1975 int nbytes_read = 0;
1976 int nbytes_written = 0;
1977
1978 memset(response, 0, sizeof(response));
1979
1980 snprintf(cmd, 16, "<%sSCDT%s>", getFocusTarget(), index > 0 ? lynxModels[ModelS[index].name].c_str() : "ZZ");
1981
1982 LOGF_DEBUG("CMD (%s)", cmd);
1983
1984 if (isSimulation())
1985 {
1986 strncpy(response, "SET", 16);
1987 nbytes_read = strlen(response) + 1;
1988 }
1989 else
1990 {
1991 tcflush(PortFD, TCIFLUSH);
1992
1993 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
1994 {
1995 tty_error_msg(errcode, errmsg, MAXRBUF);
1996 LOGF_ERROR("%s", errmsg);
1997 return false;
1998 }
1999
2000 if (!isResponseOK())
2001 return false;
2002
2003 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2004 {
2005 tty_error_msg(errcode, errmsg, MAXRBUF);
2006 LOGF_ERROR("%s", errmsg);
2007 return false;
2008 }
2009 }
2010
2011 if (nbytes_read > 0)
2012 {
2013 response[nbytes_read - 1] = '\0';
2014 LOGF_DEBUG("RES (%s)", response);
2015 tcflush(PortFD, TCIFLUSH);
2016
2017 if (!strcmp(response, "SET"))
2018 return true;
2019 else
2020 return false;
2021 }
2022
2023 return false;
2024}
2025
2026/************************************************************************************
2027 *
2028* ***********************************************************************************/
2029bool FocusLynxBase::setLedLevel(int level)
2030// Write via the connected port to the HUB the selected LED intensity level
2031
2032{
2033 char cmd[16];
2034 int errcode = 0;
2035 char errmsg[MAXRBUF];
2036 char response[LYNX_MAX] = {0};
2037 int nbytes_read = 0;
2038 int nbytes_written = 0;
2039
2040 memset(response, 0, sizeof(response));
2041
2042 snprintf(cmd, 16, "<FHSCLB%d>", level);
2043
2044 LOGF_DEBUG("CMD (%s)", cmd);
2045
2046 if (isSimulation())
2047 {
2048 strncpy(response, "SET", 16);
2049 nbytes_read = strlen(response) + 1;
2050 }
2051 else
2052 {
2053 tcflush(PortFD, TCIFLUSH);
2054
2055 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2056 {
2057 tty_error_msg(errcode, errmsg, MAXRBUF);
2058 LOGF_ERROR("%s", errmsg);
2059 return false;
2060 }
2061
2062 if (!isResponseOK())
2063 return false;
2064
2065 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2066 {
2067 tty_error_msg(errcode, errmsg, MAXRBUF);
2068 LOGF_ERROR("%s", errmsg);
2069 return false;
2070 }
2071 }
2072
2073 if (nbytes_read > 0)
2074 {
2075 response[nbytes_read - 1] = '\0';
2076 LOGF_DEBUG("RES (%s)", response);
2077 tcflush(PortFD, TCIFLUSH);
2078
2079 if (!strcmp(response, "SET"))
2080 return true;
2081 else
2082 return false;
2083 }
2084
2085 return false;
2086}
2087
2088/************************************************************************************
2089 *
2090* ***********************************************************************************/
2091bool FocusLynxBase::setDeviceNickname(const char *nickname)
2092// Write via the connected port to the HUB the choiced nikname of the focuser
2093{
2094 char cmd[LYNX_MAX] = {0};
2095 int errcode = 0;
2096 char errmsg[MAXRBUF];
2097 char response[LYNX_MAX] = {0};
2098 int nbytes_read = 0;
2099 int nbytes_written = 0;
2100
2101 memset(response, 0, sizeof(response));
2102
2103 snprintf(cmd, LYNX_MAX, "<%sSCNN%s>", getFocusTarget(), nickname);
2104
2105 LOGF_DEBUG("CMD (%s)", cmd);
2106
2107 if (isSimulation())
2108 {
2109 strncpy(response, "SET", 16);
2110 nbytes_read = strlen(response) + 1;
2111 }
2112 else
2113 {
2114 tcflush(PortFD, TCIFLUSH);
2115
2116 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2117 {
2118 tty_error_msg(errcode, errmsg, MAXRBUF);
2119 LOGF_ERROR("%s", errmsg);
2120 return false;
2121 }
2122
2123 if (!isResponseOK())
2124 return false;
2125
2126 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2127 {
2128 tty_error_msg(errcode, errmsg, MAXRBUF);
2129 LOGF_ERROR("%s", errmsg);
2130 return false;
2131 }
2132 }
2133
2134 if (nbytes_read > 0)
2135 {
2136 response[nbytes_read - 1] = '\0';
2137 LOGF_DEBUG("RES (%s)", response);
2138 tcflush(PortFD, TCIFLUSH);
2139
2140 if (!strcmp(response, "SET"))
2141 return true;
2142 else
2143 return false;
2144 }
2145
2146 return false;
2147}
2148/************************************************************************************
2149 *
2150* ***********************************************************************************/
2151bool FocusLynxBase::home()
2152{
2153 char cmd[LYNX_MAX] = {0};
2154 int errcode = 0;
2155 char errmsg[MAXRBUF];
2156 char response[LYNX_MAX] = {0};
2157 int nbytes_read = 0;
2158 int nbytes_written = 0;
2159
2160 memset(response, 0, sizeof(response));
2161
2162 snprintf(cmd, LYNX_MAX, "<%sHOME>", getFocusTarget());
2163 LOGF_DEBUG("CMD (%s)", cmd);
2164
2165 if (isSimulation())
2166 {
2167 strncpy(response, "H", 16);
2168 nbytes_read = strlen(response) + 1;
2169 targetPosition = 0;
2170 //FocusAbsPosNP[0].setValue(MaxTravelN[0].value);
2173 simStatus[STATUS_HOMING] = ISS_ON;
2174 simStatus[STATUS_HOMED] = ISS_OFF;
2175 simPosition = FocusAbsPosNP[0].getValue();
2176 }
2177 else
2178 {
2179 tcflush(PortFD, TCIFLUSH);
2180
2181 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2182 {
2183 tty_error_msg(errcode, errmsg, MAXRBUF);
2184 LOGF_ERROR("%s", errmsg);
2185 return false;
2186 }
2187
2188 if (!isResponseOK())
2189 return false;
2190
2191 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2192 {
2193 tty_error_msg(errcode, errmsg, MAXRBUF);
2194 LOGF_ERROR("%s", errmsg);
2195 return false;
2196 }
2197 }
2198
2199 if (nbytes_read > 0)
2200 {
2201 response[nbytes_read - 1] = '\0';
2202 LOGF_DEBUG("RES (%s)", response);
2205
2206 isHoming = true;
2207 LOG_INFO("Focuser is homing...");
2208
2209 tcflush(PortFD, TCIFLUSH);
2210
2211 return true;
2212 }
2213
2214 return false;
2215}
2216
2217/************************************************************************************
2218 *
2219* ***********************************************************************************/
2220bool FocusLynxBase::center()
2221{
2222 char cmd[LYNX_MAX] = {0};
2223 int errcode = 0;
2224 char errmsg[MAXRBUF];
2225 char response[LYNX_MAX] = {0};
2226 int nbytes_read = 0;
2227 int nbytes_written = 0;
2228
2229 memset(response, 0, sizeof(response));
2230
2231 snprintf(cmd, LYNX_MAX, "<%sCENTER>", getFocusTarget());
2232 LOGF_DEBUG("CMD (%s)", cmd);
2233
2234 if (isSimulation())
2235 {
2236 strncpy(response, "M", 16);
2237 nbytes_read = strlen(response) + 1;
2238 simStatus[STATUS_MOVING] = ISS_ON;
2239 targetPosition = FocusAbsPosNP[0].getMax() / 2;
2240 }
2241 else
2242 {
2243 tcflush(PortFD, TCIFLUSH);
2244
2245 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2246 {
2247 tty_error_msg(errcode, errmsg, MAXRBUF);
2248 LOGF_ERROR("%s", errmsg);
2249 return false;
2250 }
2251
2252 if (!isResponseOK())
2253 return false;
2254
2255 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2256 {
2257 tty_error_msg(errcode, errmsg, MAXRBUF);
2258 LOGF_ERROR("%s", errmsg);
2259 return false;
2260 }
2261 }
2262
2263 if (nbytes_read > 0)
2264 {
2265 response[nbytes_read - 1] = '\0';
2266 LOGF_DEBUG("RES (%s)", response);
2267
2268 LOG_INFO("Focuser moving to center position...");
2269
2272
2273 tcflush(PortFD, TCIFLUSH);
2274
2275 return true;
2276 }
2277
2278 return false;
2279}
2280
2281/************************************************************************************
2282 *
2283* ***********************************************************************************/
2284bool FocusLynxBase::setTemperatureCompensation(bool enable)
2285{
2286 char cmd[16];
2287 int errcode = 0;
2288 char errmsg[MAXRBUF];
2289 char response[LYNX_MAX] = {0};
2290 int nbytes_read = 0;
2291 int nbytes_written = 0;
2292
2293 memset(response, 0, sizeof(response));
2294
2295 snprintf(cmd, 16, "<%sSCTE%d>", getFocusTarget(), enable ? 1 : 0);
2296
2297 LOGF_DEBUG("CMD (%s)", cmd);
2298
2299 if (isSimulation())
2300 {
2301 strncpy(response, "SET", 16);
2302 nbytes_read = strlen(response) + 1;
2303 }
2304 else
2305 {
2306 tcflush(PortFD, TCIFLUSH);
2307
2308 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2309 {
2310 tty_error_msg(errcode, errmsg, MAXRBUF);
2311 LOGF_ERROR("%s", errmsg);
2312 return false;
2313 }
2314
2315 if (!isResponseOK())
2316 return false;
2317
2318 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2319 {
2320 tty_error_msg(errcode, errmsg, MAXRBUF);
2321 LOGF_ERROR("%s", errmsg);
2322 return false;
2323 }
2324 }
2325
2326 if (nbytes_read > 0)
2327 {
2328 response[nbytes_read - 1] = '\0';
2329 LOGF_DEBUG("RES (%s)", response);
2330 tcflush(PortFD, TCIFLUSH);
2331
2332 if (!strcmp(response, "SET"))
2333 return true;
2334 else
2335 return false;
2336 }
2337
2338 return false;
2339}
2340
2341/************************************************************************************
2342 *
2343* ***********************************************************************************/
2344bool FocusLynxBase::setTemperatureCompensationMode(char mode)
2345{
2346 char cmd[16];
2347 int errcode = 0;
2348 char errmsg[MAXRBUF];
2349 char response[LYNX_MAX] = {0};
2350 int nbytes_read = 0;
2351 int nbytes_written = 0;
2352
2353 memset(response, 0, sizeof(response));
2354
2355 snprintf(cmd, 16, "<%sSCTM%c>", getFocusTarget(), mode);
2356
2357 LOGF_DEBUG("CMD (%s)", cmd);
2358
2359 if (isSimulation())
2360 {
2361 strncpy(response, "SET", 16);
2362 nbytes_read = strlen(response) + 1;
2363 }
2364 else
2365 {
2366 tcflush(PortFD, TCIFLUSH);
2367
2368 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2369 {
2370 tty_error_msg(errcode, errmsg, MAXRBUF);
2371 LOGF_ERROR("%s", errmsg);
2372 return false;
2373 }
2374
2375 if (!isResponseOK())
2376 return false;
2377
2378 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2379 {
2380 tty_error_msg(errcode, errmsg, MAXRBUF);
2381 LOGF_ERROR("%s", errmsg);
2382 return false;
2383 }
2384 }
2385
2386 if (nbytes_read > 0)
2387 {
2388 response[nbytes_read - 1] = '\0';
2389 LOGF_DEBUG("RES (%s)", response);
2390 tcflush(PortFD, TCIFLUSH);
2391
2392 // If OK, the value would be read and update UI properties
2393 if (!strcmp(response, "SET"))
2394 return getFocusTemp();
2395 else
2396 return false;
2397 }
2398
2399 return false;
2400}
2401
2402/************************************************************************************
2403 *
2404* ***********************************************************************************/
2405bool FocusLynxBase::setTemperatureCompensationCoeff(char mode, int16_t coeff)
2406{
2407 char cmd[16];
2408 int errcode = 0;
2409 char errmsg[MAXRBUF];
2410 char response[LYNX_MAX] = {0};
2411 int nbytes_read = 0;
2412 int nbytes_written = 0;
2413
2414 memset(response, 0, sizeof(response));
2415
2416 snprintf(cmd, 16, "<%sSCTC%c%c%04d>", getFocusTarget(), mode, coeff >= 0 ? '+' : '-', static_cast<int>(std::abs(coeff)));
2417
2418 LOGF_DEBUG("CMD (%s)", cmd);
2419
2420 if (isSimulation())
2421 {
2422 strncpy(response, "SET", 16);
2423 nbytes_read = strlen(response) + 1;
2424 }
2425 else
2426 {
2427 tcflush(PortFD, TCIFLUSH);
2428
2429 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2430 {
2431 tty_error_msg(errcode, errmsg, MAXRBUF);
2432 LOGF_ERROR("%s", errmsg);
2433 return false;
2434 }
2435
2436 if (!isResponseOK())
2437 return false;
2438
2439 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2440 {
2441 tty_error_msg(errcode, errmsg, MAXRBUF);
2442 LOGF_ERROR("%s", errmsg);
2443 return false;
2444 }
2445 }
2446
2447 if (nbytes_read > 0)
2448 {
2449 response[nbytes_read - 1] = '\0';
2450 LOGF_DEBUG("RES (%s)", response);
2451 tcflush(PortFD, TCIFLUSH);
2452
2453 if (!strcmp(response, "SET"))
2454 return true;
2455 else
2456 return false;
2457 }
2458
2459 return false;
2460}
2461
2462/************************************************************************************
2463 *
2464* ***********************************************************************************/
2465bool FocusLynxBase::setTemperatureInceptions(char mode, int32_t inter)
2466{
2467 char cmd[LYNX_MAX] = {0};
2468 int errcode = 0;
2469 char errmsg[MAXRBUF];
2470 char response[LYNX_MAX] = {0};
2471 int nbytes_read = 0;
2472 int nbytes_written = 0;
2473
2474 memset(response, 0, sizeof(response));
2475
2476 snprintf(cmd, LYNX_MAX, "<%sSETINT%c%c%06d>", getFocusTarget(), mode, inter >= 0 ? '+' : '-',
2477 static_cast<int>(std::abs(inter)));
2478
2479 LOGF_DEBUG("CMD (%s)", cmd);
2480
2481 if (isSimulation())
2482 {
2483 strncpy(response, "SET", 16);
2484 nbytes_read = strlen(response) + 1;
2485 }
2486 else
2487 {
2488 tcflush(PortFD, TCIFLUSH);
2489
2490 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2491 {
2492 tty_error_msg(errcode, errmsg, MAXRBUF);
2493 LOGF_ERROR("%s", errmsg);
2494 return false;
2495 }
2496
2497 if (!isResponseOK())
2498 return false;
2499
2500 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2501 {
2502 tty_error_msg(errcode, errmsg, MAXRBUF);
2503 LOGF_ERROR("%s", errmsg);
2504 return false;
2505 }
2506 }
2507
2508 if (nbytes_read > 0)
2509 {
2510 response[nbytes_read - 1] = '\0';
2511 LOGF_DEBUG("RES (%s)", response);
2512 tcflush(PortFD, TCIFLUSH);
2513
2514 if (!strcmp(response, "SET"))
2515 return true;
2516 else
2517 return false;
2518 }
2519
2520 return false;
2521}
2522
2523/************************************************************************************
2524 *
2525* ***********************************************************************************/
2526bool FocusLynxBase::setTemperatureCompensationOnStart(bool enable)
2527{
2528 char cmd[16];
2529 int errcode = 0;
2530 char errmsg[MAXRBUF];
2531 char response[LYNX_MAX] = {0};
2532 int nbytes_read = 0;
2533 int nbytes_written = 0;
2534
2535 memset(response, 0, sizeof(response));
2536
2537 snprintf(cmd, 16, "<%sSCTS%d>", getFocusTarget(), enable ? 1 : 0);
2538
2539 LOGF_DEBUG("CMD (%s)", cmd);
2540
2541 if (isSimulation())
2542 {
2543 strncpy(response, "SET", 16);
2544 nbytes_read = strlen(response) + 1;
2545 }
2546 else
2547 {
2548 tcflush(PortFD, TCIFLUSH);
2549
2550 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2551 {
2552 tty_error_msg(errcode, errmsg, MAXRBUF);
2553 LOGF_ERROR("%s", errmsg);
2554 return false;
2555 }
2556
2557 if (!isResponseOK())
2558 return false;
2559
2560 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2561 {
2562 tty_error_msg(errcode, errmsg, MAXRBUF);
2563 LOGF_ERROR("%s", errmsg);
2564 return false;
2565 }
2566 }
2567
2568 if (nbytes_read > 0)
2569 {
2570 response[nbytes_read - 1] = '\0';
2571 LOGF_DEBUG("RES (%s)", response);
2572 tcflush(PortFD, TCIFLUSH);
2573
2574 if (!strcmp(response, "SET"))
2575 return true;
2576 else
2577 return false;
2578 }
2579
2580 return false;
2581}
2582
2583/************************************************************************************
2584 *
2585* ***********************************************************************************/
2586//bool FocusLynxBase::setBacklashCompensation(bool enable)
2588{
2589 char cmd[16];
2590 int errcode = 0;
2591 char errmsg[MAXRBUF];
2592 char response[LYNX_MAX] = {0};
2593 int nbytes_read = 0;
2594 int nbytes_written = 0;
2595
2596 memset(response, 0, sizeof(response));
2597
2598 snprintf(cmd, 16, "<%sSCBE%d>", getFocusTarget(), enabled ? 1 : 0);
2599
2600 LOGF_DEBUG("CMD (%s)", cmd);
2601
2602 if (isSimulation())
2603 {
2604 strncpy(response, "SET", 16);
2605 nbytes_read = strlen(response) + 1;
2606 }
2607 else
2608 {
2609 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2610 {
2611 tty_error_msg(errcode, errmsg, MAXRBUF);
2612 LOGF_ERROR("%s", errmsg);
2613 return false;
2614 }
2615
2616 if (!isResponseOK())
2617 return false;
2618
2619 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2620 {
2621 tty_error_msg(errcode, errmsg, MAXRBUF);
2622 LOGF_ERROR("%s", errmsg);
2623 return false;
2624 }
2625 }
2626
2627 if (nbytes_read > 0)
2628 {
2629 response[nbytes_read - 1] = '\0';
2630 LOGF_DEBUG("RES (%s)", response);
2631 tcflush(PortFD, TCIFLUSH);
2632
2633 if (!strcmp(response, "SET"))
2634 return true;
2635 else
2636 return false;
2637 }
2638
2639 return false;
2640}
2641
2642/************************************************************************************
2643 *
2644* ***********************************************************************************/
2645//bool FocusLynxBase::setFocusBacklashSteps(uint16_t steps)
2647{
2648 char cmd[16];
2649 int errcode = 0;
2650 char errmsg[MAXRBUF];
2651 char response[LYNX_MAX] = {0};
2652 int nbytes_read = 0;
2653 int nbytes_written = 0;
2654
2655 memset(response, 0, sizeof(response));
2656
2657 snprintf(cmd, 16, "<%sSCBS%02d>", getFocusTarget(), steps);
2658
2659 LOGF_DEBUG("CMD (%s)", cmd);
2660
2661 if (isSimulation())
2662 {
2663 strncpy(response, "SET", 16);
2664 nbytes_read = strlen(response) + 1;
2665 }
2666 else
2667 {
2668 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2669 {
2670 tty_error_msg(errcode, errmsg, MAXRBUF);
2671 LOGF_ERROR("%s", errmsg);
2672 return false;
2673 }
2674
2675 if (!isResponseOK())
2676 return false;
2677
2678 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2679 {
2680 tty_error_msg(errcode, errmsg, MAXRBUF);
2681 LOGF_ERROR("%s", errmsg);
2682 return false;
2683 }
2684 }
2685
2686 if (nbytes_read > 0)
2687 {
2688 response[nbytes_read - 1] = '\0';
2689 LOGF_DEBUG("RES (%s)", response);
2690 tcflush(PortFD, TCIFLUSH);
2691
2692 if (!strcmp(response, "SET"))
2693 return true;
2694 else
2695 return false;
2696 }
2697
2698 return false;
2699}
2700
2701/************************************************************************************
2702 *
2703* ***********************************************************************************/
2705{
2706 char cmd[16];
2707 int errcode = 0;
2708 char errmsg[MAXRBUF];
2709 char response[LYNX_MAX] = {0};
2710 int nbytes_read = 0;
2711 int nbytes_written = 0;
2712
2713 memset(response, 0, sizeof(response));
2714
2715 snprintf(cmd, 16, "<%sREVERSE%d>", getFocusTarget(), enabled ? 1 : 0);
2716
2717 LOGF_DEBUG("CMD (%s)", cmd);
2718
2719 if (isSimulation())
2720 {
2721 strncpy(response, "SET", 16);
2722 nbytes_read = strlen(response) + 1;
2723 simStatus[STATUS_REVERSE] = enabled ? ISS_ON : ISS_OFF;
2724 }
2725 else
2726 {
2727 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2728 {
2729 tty_error_msg(errcode, errmsg, MAXRBUF);
2730 LOGF_ERROR("%s", errmsg);
2731 return false;
2732 }
2733
2734 if (!isResponseOK())
2735 return false;
2736
2737 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2738 {
2739 tty_error_msg(errcode, errmsg, MAXRBUF);
2740 LOGF_ERROR("%s", errmsg);
2741 return false;
2742 }
2743 }
2744
2745 if (nbytes_read > 0)
2746 {
2747 response[nbytes_read - 1] = '\0';
2748 LOGF_DEBUG("RES (%s)", response);
2749 tcflush(PortFD, TCIFLUSH);
2750
2751 if (!strcmp(response, "SET"))
2752 return true;
2753 else
2754 return false;
2755 }
2756
2757 return false;
2758}
2759
2760/************************************************************************************
2761 *
2762* ***********************************************************************************/
2763bool FocusLynxBase::SyncFocuser(uint32_t ticks)
2764{
2765 char cmd[LYNX_MAX] = {0};
2766 int errcode = 0;
2767 char errmsg[MAXRBUF];
2768 char response[LYNX_MAX] = {0};
2769 int nbytes_read = 0;
2770 int nbytes_written = 0;
2771
2772 memset(response, 0, sizeof(response));
2773
2774 snprintf(cmd, LYNX_MAX, "<%sSCCP%06d>", getFocusTarget(), ticks);
2775 LOGF_DEBUG("CMD (%s)", cmd);
2776
2777 if (isSimulation())
2778 {
2779 simPosition = ticks;
2780 strncpy(response, "SET", 16);
2781 nbytes_read = strlen(response) + 1;
2782 }
2783 else
2784 {
2785 tcflush(PortFD, TCIFLUSH);
2786
2787 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2788 {
2789 tty_error_msg(errcode, errmsg, MAXRBUF);
2790 LOGF_ERROR("%s", errmsg);
2791 return false;
2792 }
2793
2794 if (!isResponseOK())
2795 return false;
2796
2797 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2798 {
2799 tty_error_msg(errcode, errmsg, MAXRBUF);
2800 LOGF_ERROR("%s", errmsg);
2801 return false;
2802 }
2803 }
2804
2805 if (nbytes_read > 0)
2806 {
2807 response[nbytes_read - 1] = '\0';
2808 LOGF_DEBUG("RES (%s)", response);
2809 tcflush(PortFD, TCIFLUSH);
2810
2811 if (!strcmp(response, "SET"))
2812 {
2813 LOGF_INFO("Setting current position to %d", ticks);
2814 return true;
2815 }
2816 else
2817 return false;
2818 }
2819 return false;
2820}
2821
2822/************************************************************************************
2823 *
2824* ***********************************************************************************/
2825//bool FocusLynxBase::setMaxTravel(uint16_t travel)
2827{
2828 char cmd[LYNX_MAX] = {0};
2829 int errcode = 0;
2830 char errmsg[MAXRBUF];
2831 char response[LYNX_MAX] = {0};
2832 int nbytes_read = 0;
2833 int nbytes_written = 0;
2834
2835 memset(response, 0, sizeof(response));
2836
2837 snprintf(cmd, LYNX_MAX, "<%sSETMAX%06d>", getFocusTarget(), ticks);
2838 LOGF_DEBUG("CMD (%s)", cmd);
2839
2840 SyncPresets(ticks);
2841
2842 if (isSimulation())
2843 {
2844 strncpy(response, "SET", 16);
2845 nbytes_read = strlen(response) + 1;
2846 }
2847 else
2848 {
2849 tcflush(PortFD, TCIFLUSH);
2850
2851 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2852 {
2853 tty_error_msg(errcode, errmsg, MAXRBUF);
2854 LOGF_ERROR("%s", errmsg);
2855 return false;
2856 }
2857
2858 if (!isResponseOK())
2859 return false;
2860
2861 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2862 {
2863 tty_error_msg(errcode, errmsg, MAXRBUF);
2864 LOGF_ERROR("%s", errmsg);
2865 return false;
2866 }
2867 }
2868
2869 if (nbytes_read > 0)
2870 {
2871 response[nbytes_read - 1] = '\0';
2872 LOGF_DEBUG("RES (%s)", response);
2873 tcflush(PortFD, TCIFLUSH);
2874
2875 if (!strcmp(response, "SET"))
2876 {
2877 getFocusConfig();
2878 return true;
2879 }
2880 else
2881 return false;
2882 }
2883
2884 return false;
2885}
2886
2887/************************************************************************************
2888 *
2889* ***********************************************************************************/
2890bool FocusLynxBase::setStepSize(uint16_t stepsize)
2891{
2892 char cmd[LYNX_MAX] = {0};
2893 int errcode = 0;
2894 char errmsg[MAXRBUF];
2895 char response[LYNX_MAX] = {0};
2896 int nbytes_read = 0;
2897 int nbytes_written = 0;
2898
2899 memset(response, 0, sizeof(response));
2900
2901 snprintf(cmd, LYNX_MAX, "<%sSETFSS%06d>", getFocusTarget(), stepsize);
2902 LOGF_DEBUG("CMD (%s)", cmd);
2903
2904 if (isSimulation())
2905 {
2906 strncpy(response, "SET", 16);
2907 nbytes_read = strlen(response) + 1;
2908 }
2909 else
2910 {
2911 tcflush(PortFD, TCIFLUSH);
2912
2913 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2914 {
2915 tty_error_msg(errcode, errmsg, MAXRBUF);
2916 LOGF_ERROR("%s", errmsg);
2917 return false;
2918 }
2919
2920 if (!isResponseOK())
2921 return false;
2922
2923 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2924 {
2925 tty_error_msg(errcode, errmsg, MAXRBUF);
2926 LOGF_ERROR("%s", errmsg);
2927 return false;
2928 }
2929 }
2930
2931 if (nbytes_read > 0)
2932 {
2933 response[nbytes_read - 1] = '\0';
2934 LOGF_DEBUG("RES (%s)", response);
2935 tcflush(PortFD, TCIFLUSH);
2936
2937 if (!strcmp(response, "SET"))
2938 {
2939 getFocusConfig();
2940 return true;
2941 }
2942 else
2943 return false;
2944 }
2945
2946 return false;
2947}
2948
2949/************************************************************************************
2950 *
2951* ***********************************************************************************/
2952bool FocusLynxBase::resetFactory()
2953{
2954 char cmd[LYNX_MAX] = {0};
2955 int errcode = 0;
2956 char errmsg[MAXRBUF];
2957 char response[LYNX_MAX] = {0};
2958 int nbytes_read = 0;
2959 int nbytes_written = 0;
2960
2961 memset(response, 0, sizeof(response));
2962
2963 snprintf(cmd, LYNX_MAX, "<%sRESET>", getFocusTarget());
2964 LOGF_DEBUG("CMD (%s)", cmd);
2965
2966 if (isSimulation())
2967 {
2968 strncpy(response, "SET", 16);
2969 nbytes_read = strlen(response) + 1;
2970 }
2971 else
2972 {
2973 tcflush(PortFD, TCIFLUSH);
2974
2975 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
2976 {
2977 tty_error_msg(errcode, errmsg, MAXRBUF);
2978 LOGF_ERROR("%s", errmsg);
2979 return false;
2980 }
2981
2982 if (!isResponseOK())
2983 return false;
2984
2985 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
2986 {
2987 tty_error_msg(errcode, errmsg, MAXRBUF);
2988 LOGF_ERROR("%s", errmsg);
2989 return false;
2990 }
2991 }
2992
2993 if (nbytes_read > 0)
2994 {
2995 response[nbytes_read - 1] = '\0';
2996 LOGF_DEBUG("RES (%s)", response);
2997 tcflush(PortFD, TCIFLUSH);
2998
2999 if (!strcmp(response, "SET"))
3000 {
3001 getFocusConfig();
3002 return true;
3003 }
3004 else
3005 return false;
3006 }
3007
3008 return false;
3009}
3010
3011/************************************************************************************
3012 *
3013* ***********************************************************************************/
3015{
3016 int errcode = 0;
3017 char errmsg[MAXRBUF];
3018 char response[LYNX_MAX] = {0};
3019 int nbytes_read = 0;
3020
3021 memset(response, 0, sizeof(response));
3022
3023 if (isSimulation())
3024 {
3025 strcpy(response, "!");
3026 nbytes_read = strlen(response) + 1;
3027 }
3028 else
3029 {
3030 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3031 {
3032 tty_error_msg(errcode, errmsg, MAXRBUF);
3033 LOGF_ERROR("TTY error: %s", errmsg);
3034 return false;
3035 }
3036 }
3037
3038 if (nbytes_read > 0)
3039 {
3040 response[nbytes_read - 1] = '\0';
3041 LOGF_DEBUG("RES (%s)", response);
3042
3043 if (!strcmp(response, "!"))
3044 return true;
3045 else
3046 {
3047 memset(response, 0, sizeof(response));
3048 while (strstr(response, "END") == nullptr)
3049 {
3050 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3051 {
3052 tty_error_msg(errcode, errmsg, MAXRBUF);
3053 LOGF_ERROR("TTY error: %s", errmsg);
3054 return false;
3055 }
3056 response[nbytes_read - 1] = '\0';
3057 LOGF_ERROR("Controller error: %s", response);
3058 }
3059
3060 return false;
3061 }
3062 }
3063 return true;
3064}
3065
3066/************************************************************************************
3067*
3068* ***********************************************************************************/
3069IPState FocusLynxBase::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
3070{
3071 char cmd[16];
3072 int errcode = 0;
3073 char errmsg[MAXRBUF];
3074 char response[LYNX_MAX] = {0};
3075 int nbytes_read = 0;
3076 int nbytes_written = 0;
3077
3078 memset(response, 0, sizeof(response));
3079
3080 snprintf(cmd, 16, "<%sM%cR%c>", getFocusTarget(), (dir == FOCUS_INWARD) ? 'I' : 'O', (speed == 0) ? '0' : '1');
3081
3082 LOGF_DEBUG("CMD (%s)", cmd);
3083
3084 if (isSimulation())
3085 {
3086 strncpy(response, "M", 16);
3087 nbytes_read = strlen(response) + 1;
3088 }
3089 else
3090 {
3091 tcflush(PortFD, TCIFLUSH);
3092
3093 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3094 {
3095 tty_error_msg(errcode, errmsg, MAXRBUF);
3096 LOGF_ERROR("%s", errmsg);
3097 return IPS_ALERT;
3098 }
3099
3100 if (!isResponseOK())
3101 return IPS_ALERT;
3102
3103 gettimeofday(&focusMoveStart, nullptr);
3104 focusMoveRequest = duration / 1000.0;
3105
3106 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3107 {
3108 tty_error_msg(errcode, errmsg, MAXRBUF);
3109 LOGF_ERROR("%s", errmsg);
3110 return IPS_ALERT;
3111 }
3112 }
3113
3114 if (nbytes_read > 0)
3115 {
3116 response[nbytes_read - 1] = '\0';
3117 LOGF_DEBUG("RES (%s)", response);
3118
3119 if (duration <= getCurrentPollingPeriod())
3120 {
3121 usleep(getCurrentPollingPeriod() * 1000);
3122 AbortFocuser();
3123 return IPS_OK;
3124 }
3125
3126 tcflush(PortFD, TCIFLUSH);
3127
3128 return IPS_BUSY;
3129 }
3130
3131 return IPS_ALERT;
3132}
3133
3134/************************************************************************************
3135*
3136* ***********************************************************************************/
3138{
3139 char cmd[LYNX_MAX] = {0};
3140 int errcode = 0;
3141 char errmsg[MAXRBUF];
3142 char response[LYNX_MAX] = {0};
3143 int nbytes_read = 0;
3144 int nbytes_written = 0;
3145
3146 targetPosition = targetTicks;
3147
3148 memset(response, 0, sizeof(response));
3149
3150 snprintf(cmd, LYNX_MAX, "<%sMA%06d>", getFocusTarget(), targetTicks);
3151
3152 LOGF_DEBUG("CMD (%s)", cmd);
3153
3154 if (isSimulation())
3155 {
3156 strncpy(response, "M", 16);
3157 nbytes_read = strlen(response) + 1;
3158 simStatus[STATUS_MOVING] = ISS_ON;
3159 }
3160 else
3161 {
3162 tcflush(PortFD, TCIFLUSH);
3163
3164 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3165 {
3166 tty_error_msg(errcode, errmsg, MAXRBUF);
3167 LOGF_ERROR("%s", errmsg);
3168 return IPS_ALERT;
3169 }
3170
3171 if (!isResponseOK())
3172 return IPS_ALERT;
3173
3174 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3175 {
3176 tty_error_msg(errcode, errmsg, MAXRBUF);
3177 LOGF_ERROR("%s", errmsg);
3178 return IPS_ALERT;
3179 }
3180 }
3181
3182 if (nbytes_read > 0)
3183 {
3184 response[nbytes_read - 1] = '\0';
3185 LOGF_DEBUG("RES (%s)", response);
3186
3188
3189 tcflush(PortFD, TCIFLUSH);
3190
3191 return IPS_BUSY;
3192 }
3193
3194 return IPS_ALERT;
3195}
3196
3197/************************************************************************************
3198*
3199* ***********************************************************************************/
3201{
3202 uint32_t newPosition = 0;
3203
3204 if (dir == FOCUS_INWARD)
3205 newPosition = FocusAbsPosNP[0].getValue() - ticks;
3206 else
3207 newPosition = FocusAbsPosNP[0].getValue() + ticks;
3208
3209 return MoveAbsFocuser(newPosition);
3210}
3211
3212/************************************************************************************
3213*
3214* ***********************************************************************************/
3216{
3217 if (!isConnected())
3218 return;
3219
3220 if (configurationComplete == false)
3221 {
3223 return;
3224 }
3225
3226 bool statusrc = false;
3227 for (int i = 0; i < 2; i++)
3228 {
3229 statusrc = getFocusStatus();
3230 if (statusrc)
3231 break;
3232 }
3233
3234 if (statusrc == false)
3235 {
3236 LOG_WARN("Unable to read focuser status....");
3238 return;
3239 }
3240
3242 {
3243 if (isSimulation())
3244 {
3245 if (FocusAbsPosNP[0].getValue() < targetPosition)
3246 simPosition += 100;
3247 else
3248 simPosition -= 100;
3249
3250 simStatus[STATUS_MOVING] = ISS_ON;
3251
3252 if (std::abs(static_cast<int64_t>(simPosition) - static_cast<int64_t>(targetPosition)) < 100)
3253 {
3254 FocusAbsPosNP[0].setValue(targetPosition);
3255 simPosition = FocusAbsPosNP[0].getValue();
3256 simStatus[STATUS_MOVING] = ISS_OFF;
3257 StatusL[STATUS_MOVING].s = IPS_IDLE;
3258 if (simStatus[STATUS_HOMING] == ISS_ON)
3259 {
3260 StatusL[STATUS_HOMED].s = IPS_OK;
3261 StatusL[STATUS_HOMING].s = IPS_IDLE;
3262 simStatus[STATUS_HOMING] = ISS_OFF;
3263 simStatus[STATUS_HOMED] = ISS_ON;
3264 }
3265 }
3266 else
3267 StatusL[STATUS_MOVING].s = IPS_BUSY;
3268 IDSetLight(&StatusLP, nullptr);
3269 }
3270
3271 if (isHoming && StatusL[STATUS_HOMED].s == IPS_OK)
3272 {
3273 isHoming = false;
3274 GotoSP.s = IPS_OK;
3275 IUResetSwitch(&GotoSP);
3276 GotoS[GOTO_HOME].s = ISS_ON;
3277 IDSetSwitch(&GotoSP, nullptr);
3280 LOG_INFO("Focuser completed home.");
3281 if (isSimulation())
3282 center();
3283 }
3284 else if (StatusL[STATUS_MOVING].s == IPS_IDLE)
3285 {
3290 if (GotoSP.s == IPS_BUSY)
3291 {
3292 IUResetSwitch(&GotoSP);
3293 GotoSP.s = IPS_OK;
3294 IDSetSwitch(&GotoSP, nullptr);
3295 }
3296 LOG_INFO("Focuser reached requested position.");
3297 }
3298 else if (StatusL[STATUS_MOVING].s == IPS_BUSY && focusMoveRequest > 0)
3299 {
3300 float remaining = calcTimeLeft(focusMoveStart, focusMoveRequest);
3301
3302 if (remaining < getCurrentPollingPeriod())
3303 {
3304 sleep(remaining);
3305 AbortFocuser();
3306 focusMoveRequest = 0;
3307 }
3308 }
3309 }
3310 if (StatusL[STATUS_HOMING].s == IPS_BUSY && GotoSP.s != IPS_BUSY)
3311 {
3312 GotoSP.s = IPS_BUSY;
3313 IDSetSwitch(&GotoSP, nullptr);
3314 }
3315
3317}
3318
3319/************************************************************************************
3320 *
3321* ***********************************************************************************/
3323{
3324 char cmd[LYNX_MAX] = {0};
3325 int errcode = 0;
3326 char errmsg[MAXRBUF];
3327 char response[LYNX_MAX] = {0};
3328 int nbytes_read = 0;
3329 int nbytes_written = 0;
3330
3331 memset(response, 0, sizeof(response));
3332 snprintf(cmd, LYNX_MAX, "<%sHALT>", getFocusTarget());
3333 LOGF_DEBUG("CMD (%s)", cmd);
3334
3335 if (isSimulation())
3336 {
3337 strncpy(response, "HALTED", 16);
3338 nbytes_read = strlen(response) + 1;
3339 simStatus[STATUS_MOVING] = ISS_OFF;
3340 simStatus[STATUS_HOMING] = ISS_OFF;
3341 }
3342 else
3343 {
3344 tcflush(PortFD, TCIFLUSH);
3345
3346 if ((errcode = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
3347 {
3348 tty_error_msg(errcode, errmsg, MAXRBUF);
3349 LOGF_ERROR("%s", errmsg);
3350 return false;
3351 }
3352
3353 if (!isResponseOK())
3354 return false;
3355
3356 if ((errcode = tty_read_section(PortFD, response, 0xA, LYNXFOCUS_TIMEOUT, &nbytes_read)) != TTY_OK)
3357 {
3358 tty_error_msg(errcode, errmsg, MAXRBUF);
3359 LOGF_ERROR("%s", errmsg);
3360 return false;
3361 }
3362 }
3363
3364 if (nbytes_read > 0)
3365 {
3366 response[nbytes_read - 1] = '\0';
3367 LOGF_DEBUG("RES (%s)", response);
3368
3370 {
3373 }
3374
3377 GotoSP.s = IPS_IDLE;
3378 IUResetSwitch(&GotoSP);
3381 IDSetSwitch(&GotoSP, nullptr);
3382
3383 tcflush(PortFD, TCIFLUSH);
3384
3385 return true;
3386 }
3387
3388 return false;
3389}
3390
3391/************************************************************************************
3392 *
3393* ***********************************************************************************/
3394float FocusLynxBase::calcTimeLeft(timeval start, float req)
3395{
3396 double timesince;
3397 double timeleft;
3398 struct timeval now
3399 {
3400 0, 0
3401 };
3402 gettimeofday(&now, nullptr);
3403
3404 timesince =
3405 static_cast<int>((now.tv_sec * 1000.0 + now.tv_usec / 1000)) - static_cast<int>((start.tv_sec * 1000.0 + start.tv_usec /
3406 1000));
3407 timesince = timesince / 1000;
3408 timeleft = req - timesince;
3409 return timeleft;
3410}
3411
3412/************************************************************************************
3413 *
3414* ***********************************************************************************/
3416{
3418
3420 IUSaveConfigSwitch(fp, &TemperatureCompensateSP);
3421 IUSaveConfigSwitch(fp, &TemperatureCompensateOnStartSP);
3422 //IUSaveConfigSwitch(fp, &ReverseSP);
3423 IUSaveConfigNumber(fp, &TemperatureNP);
3424 IUSaveConfigSwitch(fp, &TemperatureCompensateModeSP);
3425 //IUSaveConfigSwitch(fp, &FocusBacklashSP);
3426 //IUSaveConfigNumber(fp, &FocusBacklashNP);
3427 IUSaveConfigNumber(fp, &StepSizeNP);
3428
3429 return true;
3430}
3431
3432/************************************************************************************
3433*
3434************************************************************************************/
3435bool FocusLynxBase::loadConfig(bool silent, const char *property)
3436{
3437 bool result = true;
3438
3439 if (property == nullptr)
3440 {
3441 // Need to know the user choice for this option not store in HUB
3442 result = INDI::DefaultDevice::loadConfig(silent, "Presets") && result;
3443 if (isSimulation())
3444 {
3445 // Only load for simulation, otherwise got from the HUB
3446 result = (INDI::DefaultDevice::loadConfig(silent, "MODEL") && result);
3447 result = (INDI::DefaultDevice::loadConfig(silent, "T. COMPENSATION") && result);
3448 result = (INDI::DefaultDevice::loadConfig(silent, "T. COMPENSATION @START") && result);
3449 result = (INDI::DefaultDevice::loadConfig(silent, "REVERSE") && result);
3450 result = (INDI::DefaultDevice::loadConfig(silent, "T. COEFF") && result);
3451 result = (INDI::DefaultDevice::loadConfig(silent, "COMPENSATE MODE") && result);
3452 // result = (INDI::DefaultDevice::loadConfig(silent, "BACKLASH COMPENSATION") && result);
3453 // result = (INDI::DefaultDevice::loadConfig(silent, "BACKLASH") && result);
3454 result = (INDI::DefaultDevice::loadConfig(silent, "MAX TRAVEL") && result);
3455 result = (INDI::DefaultDevice::loadConfig(silent, "STEP SIZE") && result);
3456 result = (INDI::DefaultDevice::loadConfig(silent, "T. PARAMETERS") && result);
3457 }
3458 }
3459 else
3460 result = INDI::DefaultDevice::loadConfig(silent, property);
3461
3462 return result;
3463}
3464
3465/************************************************************************************
3466 *
3467* ***********************************************************************************/
3469{
3470 INDI_UNUSED(enable);
3471 //tty_set_debug(enable ? 1 : 0);
3472}
3473
3474/************************************************************************************
3475 *
3476* ***********************************************************************************/
3477void FocusLynxBase::setFocusTarget(const char *target)
3478// Use to set the string of the private char[] focusTarget
3479{
3480 snprintf(focusTarget, 8, "%s", target);
3481}
3482
3483/************************************************************************************
3484 *
3485* ***********************************************************************************/
3487// Use to get the string of the private char[] focusTarget
3488{
3489 return focusTarget;
3490}
3491
3492/************************************************************************************
3493 *
3494* ***********************************************************************************/
3495int FocusLynxBase::getVersion(int *major, int *minor, int *sub)
3496{
3497 INDI_UNUSED(major);
3498 INDI_UNUSED(minor);
3499 INDI_UNUSED(sub);
3500 /* For future use of implementation of new firmware 2.0.0
3501 * and give ability to keep compatible to actual 1.0.9
3502 * Will be to avoid calling to new functions
3503 * Not yet implemented in this version of the driver
3504 */
3505 char sMajor[8], sMinor[8], sSub[8];
3506 int rc = sscanf(version, "%[^.].%[^.].%s", sMajor, sMinor, sSub);
3507
3508 LOGF_DEBUG("Version major: %s, minor: %s, subversion: %s", sMajor, sMinor, sSub);
3509 *major = atoi(sMajor);
3510 *minor = atoi(sMinor);
3511 *sub = atoi(sSub);
3512 if (rc == 3)
3513 return *major;
3514 return 0; // 0 Means error in this case
3515}
double temperature
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Processes incoming new text values from the client for this device. Delegates processing to the contr...
INumberVectorProperty LedNP
virtual int getVersion(int *major, int *minor, int *sub)
virtual const char * getDefaultName() override
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
INumber LedN[1]
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
ISwitchVectorProperty ModelSP
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
ISwitch * ModelS
virtual void debugTriggered(bool enable) override
Inform driver that the debug option was triggered. This function is called after setDebug is triggere...
bool configurationComplete
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
bool setDeviceType(int index)
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual IPState MoveAbsFocuser(uint32_t targetPosition) override
MoveFocuser the focuser to an absolute position.
void setFocusTarget(const char *target)
const char * getFocusTarget()
virtual bool loadConfig(bool silent, const char *property) override
Load the last saved configuration file.
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
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.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
virtual bool saveConfigItems(FILE *fp) override
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
bool isConnected() const
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSyncNP
INDI::PropertyNumber FocusTimerNP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertySwitch FocusBacklashSP
INDI::PropertyNumber FocusBacklashNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual void SyncPresets(uint32_t ticks)
Synchronizes the range (min, max, step) of the preset number properties (PresetNP) based on the focus...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Processes incoming new text values from the client for this device. Delegates processing to the contr...
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void setPermission(IPerm permission)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
#define VERSION
#define LYNXFOCUS_TIMEOUT
#define SUBVERSION
#define FOCUS_SETTINGS_TAB
#define FOCUS_STATUS_TAB
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_ATMOST1
Definition indiapi.h:172
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:653
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
@ TTY_OK
Definition indicom.h:54
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition indidevapi.c:33
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 indidevapi.c:387
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:490
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition indidevapi.c:337
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
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 indidevapi.c:473
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:509
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition indidevapi.c:44
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition indidevapi.c:23
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition indidevapi.c:376
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
Definition indidevapi.c:317
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition indidevapi.c:416
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition indidevapi.c:398
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:453
#define INDI_UNUSED(x)
Definition indidevapi.h:132
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
#define MAXRBUF
Definition indidriver.c:52
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_WARN(txt)
Definition indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define LOG_INFO(txt)
Definition indilogger.h:74
#define getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2
One switch descriptor.
char name[MAXINDINAME]
Definition indiapi.h:419
char name[MAXINDINAME]
Definition indiapi.h:321
char name[MAXINDINAME]
Definition indiapi.h:369
char name[MAXINDINAME]
Definition indiapi.h:248