37 lynxModels[
"Optec TCF-Lynx 2"] =
"OA";
38 lynxModels[
"Optec TCF-Lynx 3"] =
"OB";
43 lynxModels[
"Optec Fast Focus Secondary Focuser"] =
"OD";
52 lynxModels[
"Optec Leo"] =
"OI";
53 lynxModels[
"Optec Leo High-Torque"] =
"OJ";
54 lynxModels[
"Optec Sagitta"] =
"OK";
55 lynxModels[
"Optec Sagitta 2"] =
"OL";
58 lynxModels[
"QuickSync / HSM Hi-Torque"] =
"FA";
59 lynxModels[
"QuickSync / HSM Hi-Speed"] =
"FB";
65 lynxModels[
"DirectSync / PDMS Hi-Torque"] =
"FD";
66 lynxModels[
"DirectSync / PDMS Hi-Speed"] =
"FF";
76 lynxModels[
"FeatherTouch Motor PDMS"] =
"FE";
78 lynxModels[
"FeatherTouch Microtouch MSM Hi-Speed"] =
"SO";
79 lynxModels[
"FeatherTouch Microtouch MSM Hi-Torque"] =
"SP";
80 lynxModels[
"Starlight Instruments - FTM with MicroTouch"] =
"SQ";
83 lynxModels[
"Televue Focuser"] =
"TA";
85 lynxModels[
"Unipolar motor (Robo-Focus)"] =
"RA";
121 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
147 IUFillNumber(&TemperatureParamN[0],
"T. Coefficient",
"",
"%.f", -9999, 9999, 100., 0.);
148 IUFillNumber(&TemperatureParamN[1],
"T. Intercept",
"",
"%.f", -32766, 32766, 100., 0.);
155 IUFillNumber(&StepSizeN[0],
"1000*microns/step",
"",
"%.f", 0, 65535, 0., 0);
161 IUFillSwitchVector(&ResetSP, ResetS, 1,
getDeviceName(),
"RESET",
"Reset",
FOCUS_SETTINGS_TAB,
IP_RW,
ISR_ATMOST1, 0,
167 IUFillSwitchVector(&GotoSP, GotoS, 2,
getDeviceName(),
"GOTO",
"Goto",
MAIN_CONTROL_TAB,
IP_RW,
ISR_1OFMANY, 0,
171 std::map<std::string, std::string>::iterator iter;
176 for (iter = lynxModels.begin(); iter != lynxModels.end(); ++iter)
190 IUFillSwitchVector(&
ModelSP,
ModelS, nModels,
getDeviceName(),
"MODEL",
"Model",
MAIN_CONTROL_TAB,
IP_RW,
ISR_1OFMANY, 0,
205 IUFillText(&HFocusNameT[0],
"FocusName",
"Focuser name",
"");
273 if (getFocusConfig() && getFocusTemp())
274 LOG_INFO(
"FocusLynx parameters updated, focuser ready for use.");
277 LOG_ERROR(
"Failed to retrieve focuser configuration settings...");
313 LOG_INFO(
"FocusLynx is online. Getting focus parameters...");
317 LOG_INFO(
"Error retrieving data from FocusLynx, please ensure FocusLynxBase controller is "
318 "powered and the port is correct.");
328 return "FocusLynxBase";
347 LOG_INFO(
"Focuser model set. Please disconnect and reconnect now...");
350 LOG_INFO(
"Focuser model set. Please connect now...");
359 if (strcmp(TemperatureCompensateSP.
name, name) == 0)
363 if (setTemperatureCompensation(TemperatureCompensateS[0].s ==
ISS_ON))
365 TemperatureCompensateSP.
s =
IPS_OK;
371 TemperatureCompensateS[prevIndex].s =
ISS_ON;
379 if (!strcmp(TemperatureCompensateOnStartSP.
name, name))
382 IUUpdateSwitch(&TemperatureCompensateOnStartSP, states, names, n);
383 if (setTemperatureCompensationOnStart(TemperatureCompensateOnStartS[0].s ==
ISS_ON))
385 TemperatureCompensateOnStartSP.
s =
IPS_OK;
391 TemperatureCompensateOnStartS[prevIndex].s =
ISS_ON;
394 IDSetSwitch(&TemperatureCompensateOnStartSP,
nullptr);
399 if (!strcmp(TemperatureCompensateModeSP.
name, name))
404 if (setTemperatureCompensationMode(mode))
406 TemperatureCompensateModeSP.
s =
IPS_OK;
412 TemperatureCompensateModeS[prevIndex].s =
ISS_ON;
415 IDSetSwitch(&TemperatureCompensateModeSP,
nullptr);
440 if (strcmp(ResetSP.
name, name) == 0)
453 if (!strcmp(GotoSP.
name, name))
502 if (!strcmp(name, HFocusNameTP.
name))
505 if (setDeviceNickname(HFocusNameT[0].text))
524 if (!strcmp(TemperatureParamNP.
name, name))
529 if (!setTemperatureCompensationCoeff(mode, TemperatureParamN[0].value) ||
530 !setTemperatureInceptions(mode, TemperatureParamN[1].value))
532 LOG_ERROR(
"Failed to write temperature coefficient or intercept");
580 if (strcmp(StepSizeNP.
name, name) == 0)
583 if (setStepSize(StepSizeN[0].value) ==
false)
585 LOG_ERROR(
"Failed to set the actual value.");
625 if (setLedLevel(
LedN[0].value))
629 LOGF_INFO(
"Focuser LED level intensity : %f",
LedN[0].value);
643 char cmd[LYNX_MAX] = {0};
646 char response[LYNX_MAX] = {0};
648 int nbytes_written = 0;
650 memset(response, 0,
sizeof(response));
658 snprintf(response, LYNX_MAX,
"%s", focusName);
659 nbytes_read = strlen(response) + 1;
683 response[nbytes_read - 1] =
'\0';
696bool FocusLynxBase::getFocusConfig()
698 char cmd[LYNX_MAX] = {0};
701 char response[LYNX_MAX] = {0};
703 int nbytes_written = 0;
706 memset(response, 0,
sizeof(response));
714 strncpy(response,
"CONFIG1", 16);
716 strncpy(response,
"CONFIG2", 16);
717 nbytes_read = strlen(response) + 1;
741 response[nbytes_read - 1] =
'\0';
744 if ((strcmp(response,
"CONFIG1")) && (strcmp(response,
"CONFIG2")))
748 memset(response, 0,
sizeof(response));
753 snprintf(response,
sizeof(response),
"NickName=Focuser#%s\n",
getFocusTarget());
754 nbytes_read = strlen(response);
762 response[nbytes_read - 1] =
'\0';
766 int rc = sscanf(response,
"%15[^=]=%15[^\n]s", key, nickname);
777 memset(response, 0,
sizeof(response));
783 snprintf(response, 32,
"Max Pos = %06d\n", 65535);
784 nbytes_read = strlen(response);
792 response[nbytes_read - 1] =
'\0';
796 rc = sscanf(response,
"%15[^=]=%d", key, &maxPos);
823 memset(response, 0,
sizeof(response));
830 snprintf(response, 32,
"Dev Type = %s\n",
"OA");
832 snprintf(response, 32,
"Dev Type = %s\n",
"SO");
833 nbytes_read = strlen(response);
841 response[nbytes_read - 1] =
'\0';
848 std::string tmpString;
849 tmpString.assign(response + 11, 2);
853 if(tmpString !=
"ZZ")
858 canHome = tmpString[0] ==
'O';
878 std::map<std::string, std::string>::iterator it = lynxModels.begin();
879 while(it != lynxModels.end())
882 if (it->second == tmpString)
899 memset(response, 0,
sizeof(response));
963 nbytes_read = strlen(response);
971 response[nbytes_read - 1] =
'\0';
975 rc = sscanf(response,
"%15[^=]=%d", key, &BLCCompensate);
986 memset(response, 0,
sizeof(response));
989 snprintf(response, 32,
"BLC Stps = %d\n", 50);
990 nbytes_read = strlen(response);
998 response[nbytes_read - 1] =
'\0';
1002 rc = sscanf(response,
"%15[^=]=%d", key, &BLCValue);
1011 memset(response, 0,
sizeof(response));
1014 snprintf(response, 32,
"LED Brt = %d\n", 75);
1015 nbytes_read = strlen(response);
1023 response[nbytes_read - 1] =
'\0';
1027 rc = sscanf(response,
"%15[^=]=%d", key, &LEDBrightness);
1031 LedN[0].value = LEDBrightness;
1053 else if (strncmp(response,
"END", 3))
1056 rc = sscanf(response,
"%15[^=]=%d", key, &homeOnStart);
1060 m_HomeOnStart = homeOnStart == 1;
1064 if (strncmp(response,
"END", 3))
1067 memset(response, 0,
sizeof(response));
1070 strncpy(response,
"END\n", 16);
1071 nbytes_read = strlen(response);
1081 if (nbytes_read > 0)
1083 response[nbytes_read - 1] =
'\0';
1088 if (strcmp(response,
"END"))
1092 tcflush(
PortFD, TCIFLUSH);
1102bool FocusLynxBase::getFocusStatus()
1104 char cmd[LYNX_MAX] = {0};
1107 char response[LYNX_MAX] = {0};
1108 int nbytes_read = 0;
1109 int nbytes_written = 0;
1112 memset(response, 0,
sizeof(response));
1120 strncpy(response,
"STATUS1", 16);
1122 strncpy(response,
"STATUS2", 16);
1123 nbytes_read = strlen(response) + 1;
1147 if (nbytes_read > 0)
1149 response[nbytes_read - 1] =
'\0';
1152 if (!((!strcmp(response,
"STATUS1")) && (!strcmp(
getFocusTarget(),
"F1"))) && !((!strcmp(response,
"STATUS2"))
1155 tcflush(
PortFD, TCIFLUSH);
1160 memset(response, 0,
sizeof(response));
1164 strcpy(response,
"Temp(C) = +21.7\n");
1165 nbytes_read = strlen(response);
1174 if (nbytes_read > 0)
1175 response[nbytes_read - 1] =
'\0';
1180 int rc = sscanf(response,
"%15[^=]=%f", key, &
temperature);
1196 memset(response, 0,
sizeof(response));
1199 snprintf(response, 32,
"Curr Pos = %06d\n", simPosition);
1200 nbytes_read = strlen(response);
1208 response[nbytes_read - 1] =
'\0';
1211 uint32_t currPos = 0;
1212 rc = sscanf(response,
"%15[^=]=%d", key, &currPos);
1222 memset(response, 0,
sizeof(response));
1225 snprintf(response, 32,
"Targ Pos = %06d\n", targetPosition);
1226 nbytes_read = strlen(response);
1234 response[nbytes_read - 1] =
'\0';
1240 memset(response, 0,
sizeof(response));
1244 nbytes_read = strlen(response);
1252 response[nbytes_read - 1] =
'\0';
1256 rc = sscanf(response,
"%15[^=]=%d", key, &isMoving);
1263 memset(response, 0,
sizeof(response));
1267 nbytes_read = strlen(response);
1275 response[nbytes_read - 1] =
'\0';
1279 rc = sscanf(response,
"%15[^=]=%d", key, &_isHoming);
1285 if (canHome ==
false)
1293 memset(response, 0,
sizeof(response));
1296 snprintf(response, 32,
"Is Homed = %d\n", (simStatus[
STATUS_HOMED] ==
ISS_ON) ? 1 : 0);
1297 nbytes_read = strlen(response);
1305 response[nbytes_read - 1] =
'\0';
1309 rc = sscanf(response,
"%15[^=]=%d", key, &isHomed);
1315 if (canHome ==
false)
1319 memset(response, 0,
sizeof(response));
1323 nbytes_read = strlen(response);
1331 response[nbytes_read - 1] =
'\0';
1335 rc = sscanf(response,
"%15[^=]=%d", key, &FFDetect);
1342 memset(response, 0,
sizeof(response));
1346 nbytes_read = strlen(response);
1354 response[nbytes_read - 1] =
'\0';
1358 rc = sscanf(response,
"%15[^=]=%d", key, &TmpProbe);
1365 memset(response, 0,
sizeof(response));
1369 nbytes_read = strlen(response);
1377 response[nbytes_read - 1] =
'\0';
1381 rc = sscanf(response,
"%15[^=]=%d", key, &RemoteIO);
1388 memset(response, 0,
sizeof(response));
1392 nbytes_read = strlen(response);
1400 response[nbytes_read - 1] =
'\0';
1404 rc = sscanf(response,
"%15[^=]=%d", key, &HndCtlr);
1411 memset(response, 0,
sizeof(response));
1415 nbytes_read = strlen(response);
1423 response[nbytes_read - 1] =
'\0';
1427 rc = sscanf(response,
"%15[^=]=%d", key, &reverse);
1448 memset(response, 0,
sizeof(response));
1451 strncpy(response,
"END\n", 16);
1452 nbytes_read = strlen(response);
1461 if (nbytes_read > 0)
1463 response[nbytes_read - 1] =
'\0';
1467 if (strcmp(response,
"END"))
1471 tcflush(
PortFD, TCIFLUSH);
1481bool FocusLynxBase::getFocusTemp()
1485 char cmd[LYNX_MAX] = {0};
1488 char response[LYNX_MAX] = {0};
1489 int nbytes_read = 0;
1490 int nbytes_written = 0;
1493 memset(response, 0,
sizeof(response));
1501 strncpy(response,
"TEMP COMP1", 16);
1503 strncpy(response,
"TEMP COMP2", 16);
1504 nbytes_read = strlen(response) + 1;
1526 if (nbytes_read > 0)
1528 response[nbytes_read - 1] =
'\0';
1531 if ((strcmp(response,
"TEMP COMP1")) && (strcmp(response,
"TEMP COMP2")))
1534 memset(response, 0,
sizeof(response));
1539 snprintf(response, 32,
"TComp ON = %d\n", TemperatureCompensateS[0].s ==
ISS_ON ? 1 : 0);
1540 nbytes_read = strlen(response);
1548 response[nbytes_read - 1] =
'\0';
1552 int rc = sscanf(response,
"%15[^=]=%d", key, &TCompOn);
1559 TemperatureCompensateSP.
s =
IPS_OK;
1562 memset(response, 0,
sizeof(response));
1567 snprintf(response, 32,
"TC Mode = %c\n",
'C');
1568 nbytes_read = strlen(response);
1576 response[nbytes_read - 1] =
'\0';
1579 char compensateMode;
1580 rc = sscanf(response,
"%15[^=]= %c", key, &compensateMode);
1583 if (rc == 1 && key[0] ==
'T')
1586 compensateMode =
'A';
1595 int index = compensateMode -
'A';
1596 if (index >= 0 && index <= 5)
1598 TemperatureCompensateModeS[index].s =
ISS_ON;
1599 TemperatureCompensateModeSP.
s =
IPS_OK;
1603 LOGF_ERROR(
"Invalid index %d for compensation mode.", index);
1607 IDSetSwitch(&TemperatureCompensateModeSP,
nullptr);
1611 memset(response, 0,
sizeof(response));
1614 snprintf(response, 32,
"TC@Start = %d\n", TemperatureCompensateOnStartS[0].s ==
ISS_ON ? 1 : 0);
1615 nbytes_read = strlen(response);
1623 response[nbytes_read - 1] =
'\0';
1627 rc = sscanf(response,
"%15[^=]=%d", key, &TCOnStart);
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);
1640 snprintf(response, 32,
"TempCo A = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1641 nbytes_read = strlen(response);
1650 if (TemperatureCompensateModeS[0].s ==
ISS_ON)
1652 response[nbytes_read - 1] =
'\0';
1656 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1660 TemperatureParamN[0].value = TCoeff;
1662 memset(response, 0,
sizeof(response));
1667 snprintf(response, 32,
"TempCo B = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1668 nbytes_read = strlen(response);
1676 if (TemperatureCompensateModeS[1].s ==
ISS_ON)
1678 response[nbytes_read - 1] =
'\0';
1682 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1686 TemperatureParamN[0].value = TCoeff;
1689 memset(response, 0,
sizeof(response));
1694 snprintf(response, 32,
"TempCo C = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1695 nbytes_read = strlen(response);
1703 if (TemperatureCompensateModeS[2].s ==
ISS_ON)
1705 response[nbytes_read - 1] =
'\0';
1709 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1713 TemperatureParamN[0].value = TCoeff;
1716 memset(response, 0,
sizeof(response));
1721 snprintf(response, 32,
"TempCo D = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1722 nbytes_read = strlen(response);
1730 if (TemperatureCompensateModeS[3].s ==
ISS_ON)
1732 response[nbytes_read - 1] =
'\0';
1736 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1740 TemperatureParamN[0].value = TCoeff;
1743 memset(response, 0,
sizeof(response));
1748 snprintf(response, 32,
"TempCo E = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1749 nbytes_read = strlen(response);
1757 if (TemperatureCompensateModeS[4].s ==
ISS_ON)
1759 response[nbytes_read - 1] =
'\0';
1763 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1767 TemperatureParamN[0].value = TCoeff;
1770 memset(response, 0,
sizeof(response));
1775 snprintf(response, 32,
"TempIn A = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1776 nbytes_read = strlen(response);
1784 if (TemperatureCompensateModeS[0].s ==
ISS_ON)
1786 response[nbytes_read - 1] =
'\0';
1790 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1794 TemperatureParamN[1].value = TInter;
1797 memset(response, 0,
sizeof(response));
1802 snprintf(response, 32,
"TempIn B = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1803 nbytes_read = strlen(response);
1811 if (TemperatureCompensateModeS[1].s ==
ISS_ON)
1813 response[nbytes_read - 1] =
'\0';
1817 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1821 TemperatureParamN[1].value = TInter;
1824 memset(response, 0,
sizeof(response));
1829 snprintf(response, 32,
"TempIn C = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1830 nbytes_read = strlen(response);
1838 if (TemperatureCompensateModeS[2].s ==
ISS_ON)
1840 response[nbytes_read - 1] =
'\0';
1844 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1848 TemperatureParamN[1].value = TInter;
1851 memset(response, 0,
sizeof(response));
1856 snprintf(response, 32,
"TempIn D = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1857 nbytes_read = strlen(response);
1865 if (TemperatureCompensateModeS[3].s ==
ISS_ON)
1867 response[nbytes_read - 1] =
'\0';
1871 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1875 TemperatureParamN[1].value = TInter;
1878 memset(response, 0,
sizeof(response));
1883 snprintf(response, 32,
"TempIn E = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1884 nbytes_read = strlen(response);
1892 if (TemperatureCompensateModeS[4].s ==
ISS_ON)
1894 response[nbytes_read - 1] =
'\0';
1898 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1902 TemperatureParamN[1].value = TInter;
1905 TemperatureParamNP.
s =
IPS_OK;
1908 memset(response, 0,
sizeof(response));
1913 snprintf(response, 32,
"StepSize = %d\n",
static_cast<int>(StepSizeN[0].value));
1914 nbytes_read = strlen(response);
1922 response[nbytes_read - 1] =
'\0';
1926 rc = sscanf(response,
"%15[^=]=%d", key, &valueStepSize);
1930 StepSizeN[0].value = valueStepSize;
1933 memset(response, 0,
sizeof(response));
1936 memset(response, 0,
sizeof(response));
1939 strncpy(response,
"END\n", 16);
1940 nbytes_read = strlen(response);
1949 if (nbytes_read > 0)
1951 response[nbytes_read - 1] =
'\0';
1955 if (strcmp(response,
"END"))
1959 tcflush(
PortFD, TCIFLUSH);
1974 char response[LYNX_MAX] = {0};
1975 int nbytes_read = 0;
1976 int nbytes_written = 0;
1978 memset(response, 0,
sizeof(response));
1986 strncpy(response,
"SET", 16);
1987 nbytes_read = strlen(response) + 1;
1991 tcflush(
PortFD, TCIFLUSH);
2011 if (nbytes_read > 0)
2013 response[nbytes_read - 1] =
'\0';
2015 tcflush(
PortFD, TCIFLUSH);
2017 if (!strcmp(response,
"SET"))
2029bool FocusLynxBase::setLedLevel(
int level)
2036 char response[LYNX_MAX] = {0};
2037 int nbytes_read = 0;
2038 int nbytes_written = 0;
2040 memset(response, 0,
sizeof(response));
2042 snprintf(
cmd, 16,
"<FHSCLB%d>", level);
2048 strncpy(response,
"SET", 16);
2049 nbytes_read = strlen(response) + 1;
2053 tcflush(
PortFD, TCIFLUSH);
2073 if (nbytes_read > 0)
2075 response[nbytes_read - 1] =
'\0';
2077 tcflush(
PortFD, TCIFLUSH);
2079 if (!strcmp(response,
"SET"))
2091bool FocusLynxBase::setDeviceNickname(
const char *nickname)
2094 char cmd[LYNX_MAX] = {0};
2097 char response[LYNX_MAX] = {0};
2098 int nbytes_read = 0;
2099 int nbytes_written = 0;
2101 memset(response, 0,
sizeof(response));
2109 strncpy(response,
"SET", 16);
2110 nbytes_read = strlen(response) + 1;
2114 tcflush(
PortFD, TCIFLUSH);
2134 if (nbytes_read > 0)
2136 response[nbytes_read - 1] =
'\0';
2138 tcflush(
PortFD, TCIFLUSH);
2140 if (!strcmp(response,
"SET"))
2151bool FocusLynxBase::home()
2153 char cmd[LYNX_MAX] = {0};
2156 char response[LYNX_MAX] = {0};
2157 int nbytes_read = 0;
2158 int nbytes_written = 0;
2160 memset(response, 0,
sizeof(response));
2167 strncpy(response,
"H", 16);
2168 nbytes_read = strlen(response) + 1;
2179 tcflush(
PortFD, TCIFLUSH);
2199 if (nbytes_read > 0)
2201 response[nbytes_read - 1] =
'\0';
2209 tcflush(
PortFD, TCIFLUSH);
2220bool FocusLynxBase::center()
2222 char cmd[LYNX_MAX] = {0};
2225 char response[LYNX_MAX] = {0};
2226 int nbytes_read = 0;
2227 int nbytes_written = 0;
2229 memset(response, 0,
sizeof(response));
2236 strncpy(response,
"M", 16);
2237 nbytes_read = strlen(response) + 1;
2243 tcflush(
PortFD, TCIFLUSH);
2263 if (nbytes_read > 0)
2265 response[nbytes_read - 1] =
'\0';
2268 LOG_INFO(
"Focuser moving to center position...");
2273 tcflush(
PortFD, TCIFLUSH);
2284bool FocusLynxBase::setTemperatureCompensation(
bool enable)
2289 char response[LYNX_MAX] = {0};
2290 int nbytes_read = 0;
2291 int nbytes_written = 0;
2293 memset(response, 0,
sizeof(response));
2301 strncpy(response,
"SET", 16);
2302 nbytes_read = strlen(response) + 1;
2306 tcflush(
PortFD, TCIFLUSH);
2326 if (nbytes_read > 0)
2328 response[nbytes_read - 1] =
'\0';
2330 tcflush(
PortFD, TCIFLUSH);
2332 if (!strcmp(response,
"SET"))
2344bool FocusLynxBase::setTemperatureCompensationMode(
char mode)
2349 char response[LYNX_MAX] = {0};
2350 int nbytes_read = 0;
2351 int nbytes_written = 0;
2353 memset(response, 0,
sizeof(response));
2361 strncpy(response,
"SET", 16);
2362 nbytes_read = strlen(response) + 1;
2366 tcflush(
PortFD, TCIFLUSH);
2386 if (nbytes_read > 0)
2388 response[nbytes_read - 1] =
'\0';
2390 tcflush(
PortFD, TCIFLUSH);
2393 if (!strcmp(response,
"SET"))
2394 return getFocusTemp();
2405bool FocusLynxBase::setTemperatureCompensationCoeff(
char mode, int16_t coeff)
2410 char response[LYNX_MAX] = {0};
2411 int nbytes_read = 0;
2412 int nbytes_written = 0;
2414 memset(response, 0,
sizeof(response));
2416 snprintf(
cmd, 16,
"<%sSCTC%c%c%04d>",
getFocusTarget(), mode, coeff >= 0 ?
'+' :
'-', static_cast<int>(
std::abs(coeff)));
2422 strncpy(response,
"SET", 16);
2423 nbytes_read = strlen(response) + 1;
2427 tcflush(
PortFD, TCIFLUSH);
2447 if (nbytes_read > 0)
2449 response[nbytes_read - 1] =
'\0';
2451 tcflush(
PortFD, TCIFLUSH);
2453 if (!strcmp(response,
"SET"))
2465bool FocusLynxBase::setTemperatureInceptions(
char mode, int32_t inter)
2467 char cmd[LYNX_MAX] = {0};
2470 char response[LYNX_MAX] = {0};
2471 int nbytes_read = 0;
2472 int nbytes_written = 0;
2474 memset(response, 0,
sizeof(response));
2476 snprintf(
cmd, LYNX_MAX,
"<%sSETINT%c%c%06d>",
getFocusTarget(), mode, inter >= 0 ?
'+' :
'-',
2477 static_cast<int>(
std::abs(inter)));
2483 strncpy(response,
"SET", 16);
2484 nbytes_read = strlen(response) + 1;
2488 tcflush(
PortFD, TCIFLUSH);
2508 if (nbytes_read > 0)
2510 response[nbytes_read - 1] =
'\0';
2512 tcflush(
PortFD, TCIFLUSH);
2514 if (!strcmp(response,
"SET"))
2526bool FocusLynxBase::setTemperatureCompensationOnStart(
bool enable)
2531 char response[LYNX_MAX] = {0};
2532 int nbytes_read = 0;
2533 int nbytes_written = 0;
2535 memset(response, 0,
sizeof(response));
2543 strncpy(response,
"SET", 16);
2544 nbytes_read = strlen(response) + 1;
2548 tcflush(
PortFD, TCIFLUSH);
2568 if (nbytes_read > 0)
2570 response[nbytes_read - 1] =
'\0';
2572 tcflush(
PortFD, TCIFLUSH);
2574 if (!strcmp(response,
"SET"))
2592 char response[LYNX_MAX] = {0};
2593 int nbytes_read = 0;
2594 int nbytes_written = 0;
2596 memset(response, 0,
sizeof(response));
2604 strncpy(response,
"SET", 16);
2605 nbytes_read = strlen(response) + 1;
2627 if (nbytes_read > 0)
2629 response[nbytes_read - 1] =
'\0';
2631 tcflush(
PortFD, TCIFLUSH);
2633 if (!strcmp(response,
"SET"))
2651 char response[LYNX_MAX] = {0};
2652 int nbytes_read = 0;
2653 int nbytes_written = 0;
2655 memset(response, 0,
sizeof(response));
2663 strncpy(response,
"SET", 16);
2664 nbytes_read = strlen(response) + 1;
2686 if (nbytes_read > 0)
2688 response[nbytes_read - 1] =
'\0';
2690 tcflush(
PortFD, TCIFLUSH);
2692 if (!strcmp(response,
"SET"))
2709 char response[LYNX_MAX] = {0};
2710 int nbytes_read = 0;
2711 int nbytes_written = 0;
2713 memset(response, 0,
sizeof(response));
2721 strncpy(response,
"SET", 16);
2722 nbytes_read = strlen(response) + 1;
2745 if (nbytes_read > 0)
2747 response[nbytes_read - 1] =
'\0';
2749 tcflush(
PortFD, TCIFLUSH);
2751 if (!strcmp(response,
"SET"))
2765 char cmd[LYNX_MAX] = {0};
2768 char response[LYNX_MAX] = {0};
2769 int nbytes_read = 0;
2770 int nbytes_written = 0;
2772 memset(response, 0,
sizeof(response));
2779 simPosition = ticks;
2780 strncpy(response,
"SET", 16);
2781 nbytes_read = strlen(response) + 1;
2785 tcflush(
PortFD, TCIFLUSH);
2805 if (nbytes_read > 0)
2807 response[nbytes_read - 1] =
'\0';
2809 tcflush(
PortFD, TCIFLUSH);
2811 if (!strcmp(response,
"SET"))
2813 LOGF_INFO(
"Setting current position to %d", ticks);
2828 char cmd[LYNX_MAX] = {0};
2831 char response[LYNX_MAX] = {0};
2832 int nbytes_read = 0;
2833 int nbytes_written = 0;
2835 memset(response, 0,
sizeof(response));
2844 strncpy(response,
"SET", 16);
2845 nbytes_read = strlen(response) + 1;
2849 tcflush(
PortFD, TCIFLUSH);
2869 if (nbytes_read > 0)
2871 response[nbytes_read - 1] =
'\0';
2873 tcflush(
PortFD, TCIFLUSH);
2875 if (!strcmp(response,
"SET"))
2890bool FocusLynxBase::setStepSize(uint16_t stepsize)
2892 char cmd[LYNX_MAX] = {0};
2895 char response[LYNX_MAX] = {0};
2896 int nbytes_read = 0;
2897 int nbytes_written = 0;
2899 memset(response, 0,
sizeof(response));
2906 strncpy(response,
"SET", 16);
2907 nbytes_read = strlen(response) + 1;
2911 tcflush(
PortFD, TCIFLUSH);
2931 if (nbytes_read > 0)
2933 response[nbytes_read - 1] =
'\0';
2935 tcflush(
PortFD, TCIFLUSH);
2937 if (!strcmp(response,
"SET"))
2952bool FocusLynxBase::resetFactory()
2954 char cmd[LYNX_MAX] = {0};
2957 char response[LYNX_MAX] = {0};
2958 int nbytes_read = 0;
2959 int nbytes_written = 0;
2961 memset(response, 0,
sizeof(response));
2968 strncpy(response,
"SET", 16);
2969 nbytes_read = strlen(response) + 1;
2973 tcflush(
PortFD, TCIFLUSH);
2993 if (nbytes_read > 0)
2995 response[nbytes_read - 1] =
'\0';
2997 tcflush(
PortFD, TCIFLUSH);
2999 if (!strcmp(response,
"SET"))
3018 char response[LYNX_MAX] = {0};
3019 int nbytes_read = 0;
3021 memset(response, 0,
sizeof(response));
3025 strcpy(response,
"!");
3026 nbytes_read = strlen(response) + 1;
3038 if (nbytes_read > 0)
3040 response[nbytes_read - 1] =
'\0';
3043 if (!strcmp(response,
"!"))
3047 memset(response, 0,
sizeof(response));
3048 while (strstr(response,
"END") ==
nullptr)
3056 response[nbytes_read - 1] =
'\0';
3057 LOGF_ERROR(
"Controller error: %s", response);
3074 char response[LYNX_MAX] = {0};
3075 int nbytes_read = 0;
3076 int nbytes_written = 0;
3078 memset(response, 0,
sizeof(response));
3086 strncpy(response,
"M", 16);
3087 nbytes_read = strlen(response) + 1;
3091 tcflush(
PortFD, TCIFLUSH);
3103 gettimeofday(&focusMoveStart,
nullptr);
3104 focusMoveRequest = duration / 1000.0;
3114 if (nbytes_read > 0)
3116 response[nbytes_read - 1] =
'\0';
3126 tcflush(
PortFD, TCIFLUSH);
3139 char cmd[LYNX_MAX] = {0};
3142 char response[LYNX_MAX] = {0};
3143 int nbytes_read = 0;
3144 int nbytes_written = 0;
3146 targetPosition = targetTicks;
3148 memset(response, 0,
sizeof(response));
3156 strncpy(response,
"M", 16);
3157 nbytes_read = strlen(response) + 1;
3162 tcflush(
PortFD, TCIFLUSH);
3182 if (nbytes_read > 0)
3184 response[nbytes_read - 1] =
'\0';
3189 tcflush(
PortFD, TCIFLUSH);
3202 uint32_t newPosition = 0;
3226 bool statusrc =
false;
3227 for (
int i = 0; i < 2; i++)
3229 statusrc = getFocusStatus();
3234 if (statusrc ==
false)
3236 LOG_WARN(
"Unable to read focuser status....");
3252 if (std::abs(
static_cast<int64_t
>(simPosition) -
static_cast<int64_t
>(targetPosition)) < 100)
3280 LOG_INFO(
"Focuser completed home.");
3296 LOG_INFO(
"Focuser reached requested position.");
3300 float remaining = calcTimeLeft(focusMoveStart, focusMoveRequest);
3306 focusMoveRequest = 0;
3324 char cmd[LYNX_MAX] = {0};
3327 char response[LYNX_MAX] = {0};
3328 int nbytes_read = 0;
3329 int nbytes_written = 0;
3331 memset(response, 0,
sizeof(response));
3337 strncpy(response,
"HALTED", 16);
3338 nbytes_read = strlen(response) + 1;
3344 tcflush(
PortFD, TCIFLUSH);
3364 if (nbytes_read > 0)
3366 response[nbytes_read - 1] =
'\0';
3383 tcflush(
PortFD, TCIFLUSH);
3394float FocusLynxBase::calcTimeLeft(timeval start,
float req)
3402 gettimeofday(&now,
nullptr);
3405 static_cast<int>((now.tv_sec * 1000.0 + now.tv_usec / 1000)) -
static_cast<int>((start.tv_sec * 1000.0 + start.tv_usec /
3407 timesince = timesince / 1000;
3408 timeleft = req - timesince;
3439 if (property ==
nullptr)
3480 snprintf(focusTarget, 8,
"%s", target);
3505 char sMajor[8], sMinor[8], sSub[8];
3506 int rc = sscanf(
version,
"%[^.].%[^.].%s", sMajor, sMinor, sSub);
3508 LOGF_DEBUG(
"Version major: %s, minor: %s, subversion: %s", sMajor, sMinor, sSub);
3509 *major = atoi(sMajor);
3510 *minor = atoi(sMinor);
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...
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...
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...
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 LYNXFOCUS_TIMEOUT
#define FOCUS_SETTINGS_TAB
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
void 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.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
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.
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
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.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void 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.
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.
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,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)