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 strncpy(response, focusName, LYNX_MAX);
659 nbytes_read = strlen(response) + 1;
683 response[nbytes_read - 1] =
'\0';
696 bool 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);
1102 bool 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';
1179 float temperature = 0;
1180 int rc = sscanf(response,
"%15[^=]=%f", key, &temperature);
1183 TemperatureN[0].value = 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);
1447 memset(response, 0,
sizeof(response));
1450 strncpy(response,
"END\n", 16);
1451 nbytes_read = strlen(response);
1460 if (nbytes_read > 0)
1462 response[nbytes_read - 1] =
'\0';
1466 if (strcmp(response,
"END"))
1470 tcflush(
PortFD, TCIFLUSH);
1480 bool FocusLynxBase::getFocusTemp()
1484 char cmd[LYNX_MAX] = {0};
1487 char response[LYNX_MAX] = {0};
1488 int nbytes_read = 0;
1489 int nbytes_written = 0;
1492 memset(response, 0,
sizeof(response));
1500 strncpy(response,
"TEMP COMP1", 16);
1502 strncpy(response,
"TEMP COMP2", 16);
1503 nbytes_read = strlen(response) + 1;
1525 if (nbytes_read > 0)
1527 response[nbytes_read - 1] =
'\0';
1530 if ((strcmp(response,
"TEMP COMP1")) && (strcmp(response,
"TEMP COMP2")))
1533 memset(response, 0,
sizeof(response));
1538 snprintf(response, 32,
"TComp ON = %d\n", TemperatureCompensateS[0].s ==
ISS_ON ? 1 : 0);
1539 nbytes_read = strlen(response);
1547 response[nbytes_read - 1] =
'\0';
1551 int rc = sscanf(response,
"%15[^=]=%d", key, &TCompOn);
1558 TemperatureCompensateSP.
s =
IPS_OK;
1561 memset(response, 0,
sizeof(response));
1566 snprintf(response, 32,
"TC Mode = %c\n",
'C');
1567 nbytes_read = strlen(response);
1575 response[nbytes_read - 1] =
'\0';
1578 char compensateMode;
1579 rc = sscanf(response,
"%15[^=]= %c", key, &compensateMode);
1582 if (rc == 1 && key[0] ==
'T')
1585 compensateMode =
'A';
1594 int index = compensateMode -
'A';
1595 if (index >= 0 && index <= 5)
1597 TemperatureCompensateModeS[index].s =
ISS_ON;
1598 TemperatureCompensateModeSP.
s =
IPS_OK;
1602 LOGF_ERROR(
"Invalid index %d for compensation mode.", index);
1606 IDSetSwitch(&TemperatureCompensateModeSP,
nullptr);
1610 memset(response, 0,
sizeof(response));
1613 snprintf(response, 32,
"TC@Start = %d\n", TemperatureCompensateOnStartS[0].s ==
ISS_ON ? 1 : 0);
1614 nbytes_read = strlen(response);
1622 response[nbytes_read - 1] =
'\0';
1626 rc = sscanf(response,
"%15[^=]=%d", key, &TCOnStart);
1631 TemperatureCompensateOnStartS[0].s = TCOnStart ?
ISS_ON :
ISS_OFF;
1632 TemperatureCompensateOnStartS[1].s = TCOnStart ?
ISS_OFF :
ISS_ON;
1633 TemperatureCompensateOnStartSP.
s =
IPS_OK;
1634 IDSetSwitch(&TemperatureCompensateOnStartSP,
nullptr);
1639 snprintf(response, 32,
"TempCo A = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1640 nbytes_read = strlen(response);
1649 if (TemperatureCompensateModeS[0].s ==
ISS_ON)
1651 response[nbytes_read - 1] =
'\0';
1655 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1659 TemperatureParamN[0].value = TCoeff;
1661 memset(response, 0,
sizeof(response));
1666 snprintf(response, 32,
"TempCo B = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1667 nbytes_read = strlen(response);
1675 if (TemperatureCompensateModeS[1].s ==
ISS_ON)
1677 response[nbytes_read - 1] =
'\0';
1681 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1685 TemperatureParamN[0].value = TCoeff;
1688 memset(response, 0,
sizeof(response));
1693 snprintf(response, 32,
"TempCo C = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1694 nbytes_read = strlen(response);
1702 if (TemperatureCompensateModeS[2].s ==
ISS_ON)
1704 response[nbytes_read - 1] =
'\0';
1708 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1712 TemperatureParamN[0].value = TCoeff;
1715 memset(response, 0,
sizeof(response));
1720 snprintf(response, 32,
"TempCo D = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1721 nbytes_read = strlen(response);
1729 if (TemperatureCompensateModeS[3].s ==
ISS_ON)
1731 response[nbytes_read - 1] =
'\0';
1735 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1739 TemperatureParamN[0].value = TCoeff;
1742 memset(response, 0,
sizeof(response));
1747 snprintf(response, 32,
"TempCo E = %d\n",
static_cast<int>(TemperatureParamN[0].value));
1748 nbytes_read = strlen(response);
1756 if (TemperatureCompensateModeS[4].s ==
ISS_ON)
1758 response[nbytes_read - 1] =
'\0';
1762 rc = sscanf(response,
"%15[^=]=%d", key, &TCoeff);
1766 TemperatureParamN[0].value = TCoeff;
1769 memset(response, 0,
sizeof(response));
1774 snprintf(response, 32,
"TempIn A = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1775 nbytes_read = strlen(response);
1783 if (TemperatureCompensateModeS[0].s ==
ISS_ON)
1785 response[nbytes_read - 1] =
'\0';
1789 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1793 TemperatureParamN[1].value = TInter;
1796 memset(response, 0,
sizeof(response));
1801 snprintf(response, 32,
"TempIn B = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1802 nbytes_read = strlen(response);
1810 if (TemperatureCompensateModeS[1].s ==
ISS_ON)
1812 response[nbytes_read - 1] =
'\0';
1816 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1820 TemperatureParamN[1].value = TInter;
1823 memset(response, 0,
sizeof(response));
1828 snprintf(response, 32,
"TempIn C = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1829 nbytes_read = strlen(response);
1837 if (TemperatureCompensateModeS[2].s ==
ISS_ON)
1839 response[nbytes_read - 1] =
'\0';
1843 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1847 TemperatureParamN[1].value = TInter;
1850 memset(response, 0,
sizeof(response));
1855 snprintf(response, 32,
"TempIn D = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1856 nbytes_read = strlen(response);
1864 if (TemperatureCompensateModeS[3].s ==
ISS_ON)
1866 response[nbytes_read - 1] =
'\0';
1870 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1874 TemperatureParamN[1].value = TInter;
1877 memset(response, 0,
sizeof(response));
1882 snprintf(response, 32,
"TempIn E = %d\n",
static_cast<int>(TemperatureParamN[1].value));
1883 nbytes_read = strlen(response);
1891 if (TemperatureCompensateModeS[4].s ==
ISS_ON)
1893 response[nbytes_read - 1] =
'\0';
1897 rc = sscanf(response,
"%15[^=]=%d", key, &TInter);
1901 TemperatureParamN[1].value = TInter;
1904 TemperatureParamNP.
s =
IPS_OK;
1907 memset(response, 0,
sizeof(response));
1912 snprintf(response, 32,
"StepSize = %d\n",
static_cast<int>(StepSizeN[0].value));
1913 nbytes_read = strlen(response);
1921 response[nbytes_read - 1] =
'\0';
1925 rc = sscanf(response,
"%15[^=]=%d", key, &valueStepSize);
1929 StepSizeN[0].value = valueStepSize;
1932 memset(response, 0,
sizeof(response));
1935 memset(response, 0,
sizeof(response));
1938 strncpy(response,
"END\n", 16);
1939 nbytes_read = strlen(response);
1948 if (nbytes_read > 0)
1950 response[nbytes_read - 1] =
'\0';
1954 if (strcmp(response,
"END"))
1958 tcflush(
PortFD, TCIFLUSH);
1973 char response[LYNX_MAX] = {0};
1974 int nbytes_read = 0;
1975 int nbytes_written = 0;
1977 memset(response, 0,
sizeof(response));
1985 strncpy(response,
"SET", 16);
1986 nbytes_read = strlen(response) + 1;
1990 tcflush(
PortFD, TCIFLUSH);
2010 if (nbytes_read > 0)
2012 response[nbytes_read - 1] =
'\0';
2014 tcflush(
PortFD, TCIFLUSH);
2016 if (!strcmp(response,
"SET"))
2028 bool FocusLynxBase::setLedLevel(
int level)
2035 char response[LYNX_MAX] = {0};
2036 int nbytes_read = 0;
2037 int nbytes_written = 0;
2039 memset(response, 0,
sizeof(response));
2041 snprintf(
cmd, 16,
"<FHSCLB%d>", level);
2047 strncpy(response,
"SET", 16);
2048 nbytes_read = strlen(response) + 1;
2052 tcflush(
PortFD, TCIFLUSH);
2072 if (nbytes_read > 0)
2074 response[nbytes_read - 1] =
'\0';
2076 tcflush(
PortFD, TCIFLUSH);
2078 if (!strcmp(response,
"SET"))
2090 bool FocusLynxBase::setDeviceNickname(
const char *nickname)
2093 char cmd[LYNX_MAX] = {0};
2096 char response[LYNX_MAX] = {0};
2097 int nbytes_read = 0;
2098 int nbytes_written = 0;
2100 memset(response, 0,
sizeof(response));
2108 strncpy(response,
"SET", 16);
2109 nbytes_read = strlen(response) + 1;
2113 tcflush(
PortFD, TCIFLUSH);
2133 if (nbytes_read > 0)
2135 response[nbytes_read - 1] =
'\0';
2137 tcflush(
PortFD, TCIFLUSH);
2139 if (!strcmp(response,
"SET"))
2150 bool FocusLynxBase::home()
2152 char cmd[LYNX_MAX] = {0};
2155 char response[LYNX_MAX] = {0};
2156 int nbytes_read = 0;
2157 int nbytes_written = 0;
2159 memset(response, 0,
sizeof(response));
2166 strncpy(response,
"H", 16);
2167 nbytes_read = strlen(response) + 1;
2178 tcflush(
PortFD, TCIFLUSH);
2198 if (nbytes_read > 0)
2200 response[nbytes_read - 1] =
'\0';
2208 tcflush(
PortFD, TCIFLUSH);
2219 bool FocusLynxBase::center()
2221 char cmd[LYNX_MAX] = {0};
2224 char response[LYNX_MAX] = {0};
2225 int nbytes_read = 0;
2226 int nbytes_written = 0;
2228 memset(response, 0,
sizeof(response));
2235 strncpy(response,
"M", 16);
2236 nbytes_read = strlen(response) + 1;
2242 tcflush(
PortFD, TCIFLUSH);
2262 if (nbytes_read > 0)
2264 response[nbytes_read - 1] =
'\0';
2267 LOG_INFO(
"Focuser moving to center position...");
2272 tcflush(
PortFD, TCIFLUSH);
2283 bool FocusLynxBase::setTemperatureCompensation(
bool enable)
2288 char response[LYNX_MAX] = {0};
2289 int nbytes_read = 0;
2290 int nbytes_written = 0;
2292 memset(response, 0,
sizeof(response));
2300 strncpy(response,
"SET", 16);
2301 nbytes_read = strlen(response) + 1;
2305 tcflush(
PortFD, TCIFLUSH);
2325 if (nbytes_read > 0)
2327 response[nbytes_read - 1] =
'\0';
2329 tcflush(
PortFD, TCIFLUSH);
2331 if (!strcmp(response,
"SET"))
2343 bool FocusLynxBase::setTemperatureCompensationMode(
char mode)
2348 char response[LYNX_MAX] = {0};
2349 int nbytes_read = 0;
2350 int nbytes_written = 0;
2352 memset(response, 0,
sizeof(response));
2360 strncpy(response,
"SET", 16);
2361 nbytes_read = strlen(response) + 1;
2365 tcflush(
PortFD, TCIFLUSH);
2385 if (nbytes_read > 0)
2387 response[nbytes_read - 1] =
'\0';
2389 tcflush(
PortFD, TCIFLUSH);
2392 if (!strcmp(response,
"SET"))
2393 return getFocusTemp();
2404 bool FocusLynxBase::setTemperatureCompensationCoeff(
char mode, int16_t coeff)
2409 char response[LYNX_MAX] = {0};
2410 int nbytes_read = 0;
2411 int nbytes_written = 0;
2413 memset(response, 0,
sizeof(response));
2415 snprintf(
cmd, 16,
"<%sSCTC%c%c%04d>",
getFocusTarget(), mode, coeff >= 0 ?
'+' :
'-',
static_cast<int>(std::abs(coeff)));
2421 strncpy(response,
"SET", 16);
2422 nbytes_read = strlen(response) + 1;
2426 tcflush(
PortFD, TCIFLUSH);
2446 if (nbytes_read > 0)
2448 response[nbytes_read - 1] =
'\0';
2450 tcflush(
PortFD, TCIFLUSH);
2452 if (!strcmp(response,
"SET"))
2464 bool FocusLynxBase::setTemperatureInceptions(
char mode, int32_t inter)
2466 char cmd[LYNX_MAX] = {0};
2469 char response[LYNX_MAX] = {0};
2470 int nbytes_read = 0;
2471 int nbytes_written = 0;
2473 memset(response, 0,
sizeof(response));
2475 snprintf(
cmd, LYNX_MAX,
"<%sSETINT%c%c%06d>",
getFocusTarget(), mode, inter >= 0 ?
'+' :
'-',
2476 static_cast<int>(std::abs(inter)));
2482 strncpy(response,
"SET", 16);
2483 nbytes_read = strlen(response) + 1;
2487 tcflush(
PortFD, TCIFLUSH);
2507 if (nbytes_read > 0)
2509 response[nbytes_read - 1] =
'\0';
2511 tcflush(
PortFD, TCIFLUSH);
2513 if (!strcmp(response,
"SET"))
2525 bool FocusLynxBase::setTemperatureCompensationOnStart(
bool enable)
2530 char response[LYNX_MAX] = {0};
2531 int nbytes_read = 0;
2532 int nbytes_written = 0;
2534 memset(response, 0,
sizeof(response));
2542 strncpy(response,
"SET", 16);
2543 nbytes_read = strlen(response) + 1;
2547 tcflush(
PortFD, TCIFLUSH);
2567 if (nbytes_read > 0)
2569 response[nbytes_read - 1] =
'\0';
2571 tcflush(
PortFD, TCIFLUSH);
2573 if (!strcmp(response,
"SET"))
2591 char response[LYNX_MAX] = {0};
2592 int nbytes_read = 0;
2593 int nbytes_written = 0;
2595 memset(response, 0,
sizeof(response));
2603 strncpy(response,
"SET", 16);
2604 nbytes_read = strlen(response) + 1;
2626 if (nbytes_read > 0)
2628 response[nbytes_read - 1] =
'\0';
2630 tcflush(
PortFD, TCIFLUSH);
2632 if (!strcmp(response,
"SET"))
2650 char response[LYNX_MAX] = {0};
2651 int nbytes_read = 0;
2652 int nbytes_written = 0;
2654 memset(response, 0,
sizeof(response));
2662 strncpy(response,
"SET", 16);
2663 nbytes_read = strlen(response) + 1;
2685 if (nbytes_read > 0)
2687 response[nbytes_read - 1] =
'\0';
2689 tcflush(
PortFD, TCIFLUSH);
2691 if (!strcmp(response,
"SET"))
2708 char response[LYNX_MAX] = {0};
2709 int nbytes_read = 0;
2710 int nbytes_written = 0;
2712 memset(response, 0,
sizeof(response));
2720 strncpy(response,
"SET", 16);
2721 nbytes_read = strlen(response) + 1;
2744 if (nbytes_read > 0)
2746 response[nbytes_read - 1] =
'\0';
2748 tcflush(
PortFD, TCIFLUSH);
2750 if (!strcmp(response,
"SET"))
2764 char cmd[LYNX_MAX] = {0};
2767 char response[LYNX_MAX] = {0};
2768 int nbytes_read = 0;
2769 int nbytes_written = 0;
2771 memset(response, 0,
sizeof(response));
2778 simPosition = ticks;
2779 strncpy(response,
"SET", 16);
2780 nbytes_read = strlen(response) + 1;
2784 tcflush(
PortFD, TCIFLUSH);
2804 if (nbytes_read > 0)
2806 response[nbytes_read - 1] =
'\0';
2808 tcflush(
PortFD, TCIFLUSH);
2810 if (!strcmp(response,
"SET"))
2812 LOGF_INFO(
"Setting current position to %d", ticks);
2827 char cmd[LYNX_MAX] = {0};
2830 char response[LYNX_MAX] = {0};
2831 int nbytes_read = 0;
2832 int nbytes_written = 0;
2834 memset(response, 0,
sizeof(response));
2843 strncpy(response,
"SET", 16);
2844 nbytes_read = strlen(response) + 1;
2848 tcflush(
PortFD, TCIFLUSH);
2868 if (nbytes_read > 0)
2870 response[nbytes_read - 1] =
'\0';
2872 tcflush(
PortFD, TCIFLUSH);
2874 if (!strcmp(response,
"SET"))
2889 bool FocusLynxBase::setStepSize(uint16_t stepsize)
2891 char cmd[LYNX_MAX] = {0};
2894 char response[LYNX_MAX] = {0};
2895 int nbytes_read = 0;
2896 int nbytes_written = 0;
2898 memset(response, 0,
sizeof(response));
2905 strncpy(response,
"SET", 16);
2906 nbytes_read = strlen(response) + 1;
2910 tcflush(
PortFD, TCIFLUSH);
2930 if (nbytes_read > 0)
2932 response[nbytes_read - 1] =
'\0';
2934 tcflush(
PortFD, TCIFLUSH);
2936 if (!strcmp(response,
"SET"))
2951 bool FocusLynxBase::resetFactory()
2953 char cmd[LYNX_MAX] = {0};
2956 char response[LYNX_MAX] = {0};
2957 int nbytes_read = 0;
2958 int nbytes_written = 0;
2960 memset(response, 0,
sizeof(response));
2967 strncpy(response,
"SET", 16);
2968 nbytes_read = strlen(response) + 1;
2972 tcflush(
PortFD, TCIFLUSH);
2992 if (nbytes_read > 0)
2994 response[nbytes_read - 1] =
'\0';
2996 tcflush(
PortFD, TCIFLUSH);
2998 if (!strcmp(response,
"SET"))
3017 char response[LYNX_MAX] = {0};
3018 int nbytes_read = 0;
3020 memset(response, 0,
sizeof(response));
3024 strcpy(response,
"!");
3025 nbytes_read = strlen(response) + 1;
3037 if (nbytes_read > 0)
3039 response[nbytes_read - 1] =
'\0';
3042 if (!strcmp(response,
"!"))
3046 memset(response, 0,
sizeof(response));
3047 while (strstr(response,
"END") ==
nullptr)
3055 response[nbytes_read - 1] =
'\0';
3056 LOGF_ERROR(
"Controller error: %s", response);
3073 char response[LYNX_MAX] = {0};
3074 int nbytes_read = 0;
3075 int nbytes_written = 0;
3077 memset(response, 0,
sizeof(response));
3085 strncpy(response,
"M", 16);
3086 nbytes_read = strlen(response) + 1;
3090 tcflush(
PortFD, TCIFLUSH);
3102 gettimeofday(&focusMoveStart,
nullptr);
3103 focusMoveRequest = duration / 1000.0;
3113 if (nbytes_read > 0)
3115 response[nbytes_read - 1] =
'\0';
3125 tcflush(
PortFD, TCIFLUSH);
3138 char cmd[LYNX_MAX] = {0};
3141 char response[LYNX_MAX] = {0};
3142 int nbytes_read = 0;
3143 int nbytes_written = 0;
3145 targetPosition = targetTicks;
3147 memset(response, 0,
sizeof(response));
3155 strncpy(response,
"M", 16);
3156 nbytes_read = strlen(response) + 1;
3161 tcflush(
PortFD, TCIFLUSH);
3181 if (nbytes_read > 0)
3183 response[nbytes_read - 1] =
'\0';
3188 tcflush(
PortFD, TCIFLUSH);
3201 uint32_t newPosition = 0;
3225 bool statusrc =
false;
3226 for (
int i = 0; i < 2; i++)
3228 statusrc = getFocusStatus();
3233 if (statusrc ==
false)
3235 LOG_WARN(
"Unable to read focuser status....");
3251 if (std::abs(
static_cast<int64_t
>(simPosition) -
static_cast<int64_t
>(targetPosition)) < 100)
3279 LOG_INFO(
"Focuser completed home.");
3295 LOG_INFO(
"Focuser reached requested position.");
3299 float remaining = calcTimeLeft(focusMoveStart, focusMoveRequest);
3305 focusMoveRequest = 0;
3323 char cmd[LYNX_MAX] = {0};
3326 char response[LYNX_MAX] = {0};
3327 int nbytes_read = 0;
3328 int nbytes_written = 0;
3330 memset(response, 0,
sizeof(response));
3336 strncpy(response,
"HALTED", 16);
3337 nbytes_read = strlen(response) + 1;
3343 tcflush(
PortFD, TCIFLUSH);
3363 if (nbytes_read > 0)
3365 response[nbytes_read - 1] =
'\0';
3382 tcflush(
PortFD, TCIFLUSH);
3393 float FocusLynxBase::calcTimeLeft(timeval start,
float req)
3401 gettimeofday(&now,
nullptr);
3404 static_cast<int>((now.tv_sec * 1000.0 + now.tv_usec / 1000)) -
static_cast<int>((start.tv_sec * 1000.0 + start.tv_usec /
3406 timesince = timesince / 1000;
3407 timeleft = req - timesince;
3438 if (property ==
nullptr)
3479 strncpy(focusTarget, target, 8);
3504 char sMajor[8], sMinor[8], sSub[8];
3505 int rc = sscanf(
version,
"%[^.].%[^.].%s", sMajor, sMinor, sSub);
3507 LOGF_DEBUG(
"Version major: %s, minor: %s, subversion: %s", sMajor, sMinor, sSub);
3508 *major = atoi(sMajor);
3509 *minor = atoi(sMinor);
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
INumberVectorProperty LedNP
virtual int getVersion(int *major, int *minor, int *sub)
virtual const char * getDefaultName() override
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
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
Process the client newSwitch command.
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
Initilize properties initial state and value. The child class must implement this function.
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
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool Handshake() override
perform handshake with device to check communication
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
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
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
Process the client newNumber command.
const char * getDeviceName() 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.
INumberVectorProperty FocusSyncNP
INumberVectorProperty FocusBacklashNP
ISwitchVectorProperty FocusBacklashSP
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
INumberVectorProperty FocusTimerNP
ISwitchVectorProperty FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INumber FocusBacklashN[1]
INumberVectorProperty FocusMaxPosNP
ISwitch FocusBacklashS[2]
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual void SyncPresets(uint32_t ticks)
syncPresets Updates the min/max/step range of the preset as per the maximum name of Absolute Focus Tr...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
#define FOCUS_SETTINGS_TAB
#define LYNXFOCUS_TIMEOUT
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.
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
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.
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 IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
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,...)
std::vector< uint8_t > buffer
@ key
the parser read a key of a value in an object