7#ifndef tcsInterface_hpp
8#define tcsInterface_hpp
13#include "../../libMagAOX/libMagAOX.hpp"
14#include "../../magaox_git_version.h"
16#include "../../libMagAOX/app/dev/telemeter.hpp"
180 mx::app::appConfigurator &
_config );
411 config.add(
"labMode",
419 "Flag to enable lab mode. Default is true." );
421 config.add(
"pyrNudger.C_00",
429 "Pyramid to AEG control matrix [0,0] of a 2x2 matrix" );
430 config.add(
"pyrNudger.C_01",
438 "Pyramid to AEG control matrix [0,1] of a 2x2 matrix " );
439 config.add(
"pyrNudger.C_10",
447 "Pyramid to AEG control matrix [1,0] of a 2x2 matrix " );
448 config.add(
"pyrNudger.C_11",
456 "Pyramid to AEG control matrix [1,1] of a 2x2 matrix " );
458 config.add(
"pyrNudger.ang",
"",
"pyrNudger.ang", argType::Required,
"pyrNudger",
"ang",
false,
"float",
"" );
459 config.add(
"pyrNudger.ang0",
"",
"pyrNudger.ang0", argType::Required,
"pyrNudger0",
"ang0",
false,
"float",
"" );
461 "pyrNudger.parity",
"",
"pyrNudger.parity", argType::Required,
"pyrNudger",
"parity",
false,
"float",
"" );
463 config.add(
"pyrNudger.F_sign",
471 "Pyramid to AEG control matrix [1,1] of a 2x2 matrix " );
473 config.add(
"acqFromGuider.zdSign",
475 "acqFromGuider.zdSign",
481 "Sign of the Zd to rotation angle, +1 or -1, -1 default" );
482 config.add(
"acqFromGuider.az0",
490 "az component of acquisition vector a 0 zd." );
491 config.add(
"acqFromGuider.azoff",
493 "acqFromGuider.azoff",
499 "static offset to az component of acquisition vector" );
500 config.add(
"acqFromGuider.el0",
508 "el component of acquisition vector a 0 zd." );
509 config.add(
"acqFromGuider.eloff",
511 "acqFromGuider.eloff",
517 "static offset to el component of acquisition vector" );
518 config.add(
"acqFromGuider.focus",
520 "acqFromGuider.focus",
526 "static offset for focus acquisition" );
528 config.add(
"offload.TT_avgInt",
536 "Woofer to Telescope T/T offload averaging interval [sec] " );
537 config.add(
"offload.TT_gain",
545 "Woofer to Telescope T/T offload gain" );
546 config.add(
"offload.TT_thresh",
554 "Woofer to Telescope T/T offload threshold" );
556 config.add(
"offload.lab_TT_C_00",
558 "offload.lab_TT_C_00",
564 "Woofer to TTM T/T offload control matrix [0,0] of a 2x2 matrix" );
565 config.add(
"offload.lab_TT_C_01",
567 "offload.lab_TT_C_01",
573 "Woofer to TTM T/T offload control matrix [0,1] of a 2x2 matrix " );
574 config.add(
"offload.lab_TT_C_10",
576 "offload.lab_TT_C_10",
582 "Woofer to TTM T/T offload control matrix [1,0] of a 2x2 matrix " );
583 config.add(
"offload.lab_TT_C_11",
585 "offload.lab_TT_C_11",
591 "Woofer to TTM T/T offload control matrix [1,1] of a 2x2 matrix " );
593 config.add(
"offload.TT_C_00",
601 "Woofer to Telescope T/T offload control matrix [0,0] of a 2x2 matrix" );
602 config.add(
"offload.TT_C_01",
610 "Woofer to Telescope T/T offload control matrix [0,1] of a 2x2 matrix " );
611 config.add(
"offload.TT_C_10",
619 "Woofer to Telescope T/T offload control matrix [1,0] of a 2x2 matrix " );
620 config.add(
"offload.TT_C_11",
628 "Woofer to Telescope T/T offload control matrix [1,1] of a 2x2 matrix " );
630 config.add(
"offload.F_avgInt",
638 "Woofer to Telescope Focus offload averaging interval [sec] " );
639 config.add(
"offload.F_gain",
647 "Woofer to Telescope Focus offload gain" );
648 config.add(
"offload.F_thresh",
656 "Woofer to Telescope Focus offload threshold" );
658 config.add(
"offload.CFocus00",
666 "Woofer to Telescope Focus offload control scale factor." );
668 config.add(
"offload.CComa00",
676 "Woofer to Telescope Coma offload control matrix [0,0] of a 2x2 matrix" );
677 config.add(
"offload.CComa01",
685 "Woofer to Telescope Coma offload control matrix [0,1] of a 2x2 matrix " );
686 config.add(
"offload.CComa10",
694 "Woofer to Telescope Coma offload control matrix [1,0] of a 2x2 matrix " );
695 config.add(
"offload.CComa11",
703 "Woofer to Telescope Coma offload control matrix [1,1] of a 2x2 matrix " );
705 config.add(
"device.address",
713 "The IP address or resolvable name of the TCS." );
714 config.add(
"device.port",
722 "The IP port for TCS communications. Should be the command port. Default is 5811." );
806 indi::addNumberElement<double>(
807 m_indiP_teltime,
"sidereal_time", 0, std::numeric_limits<double>::max(), 0,
"%0.6f" );
812 indi::addNumberElement<double>(
m_indiP_telpos,
"epoch", 0, std::numeric_limits<double>::max(), 0,
"%0.6f" );
814 indi::addNumberElement<double>(
m_indiP_telpos,
"ra", 0, 360, 0,
"%0.6f" );
816 indi::addNumberElement<double>(
m_indiP_telpos,
"dec", -90, 90, 0,
"%0.6f" );
818 indi::addNumberElement<double>(
m_indiP_telpos,
"el", 0, 90, 0,
"%0.6f" );
820 indi::addNumberElement<double>(
m_indiP_telpos,
"ha", -180, 160, 0,
"%0.6f" );
822 indi::addNumberElement<double>(
m_indiP_telpos,
"am", 0, 4, 0,
"%0.2f" );
824 indi::addNumberElement<double>(
m_indiP_telpos,
"rotoff", 0, 360, 0,
"%0.6f" );
832 indi::addNumberElement<int>(
m_indiP_teldata,
"tracking", 0, 1, 1,
"%d" );
834 indi::addNumberElement<int>(
m_indiP_teldata,
"guiding", 0, 1, 1,
"%d" );
836 indi::addNumberElement<int>(
m_indiP_teldata,
"slewing", 0, 1, 1,
"%d" );
838 indi::addNumberElement<int>(
m_indiP_teldata,
"guider_moving", 0, 1, 1,
"%d" );
840 indi::addNumberElement<double>(
m_indiP_teldata,
"az", 0, 360, 0,
"%0.6f" );
842 indi::addNumberElement<double>(
m_indiP_teldata,
"zd", 0, 90, 0,
"%0.6f" );
844 indi::addNumberElement<double>(
m_indiP_teldata,
"pa", 0, 360, 0,
"%0.6f" );
846 indi::addNumberElement<double>(
m_indiP_teldata,
"dome_az", 0, 360, 0,
"%0.6f" );
848 indi::addNumberElement<int>(
m_indiP_teldata,
"dome_stat", 0, 1, 1,
"%d" );
860 indi::addNumberElement<double>(
m_indiP_catdata,
"ra", 0, 360, 0,
"%0.6f" );
862 indi::addNumberElement<double>(
m_indiP_catdata,
"dec", -90, 90, 0,
"%0.6f" );
864 indi::addNumberElement<double>(
m_indiP_catdata,
"epoch", 0, std::numeric_limits<double>::max(), 0,
"%0.6f" );
866 indi::addNumberElement<double>(
m_indiP_catdata,
"rotoff", 0, 360, 0,
"%0.6f" );
874 std::numeric_limits<double>::lowest(),
875 std::numeric_limits<double>::max(),
881 std::numeric_limits<double>::lowest(),
882 std::numeric_limits<double>::max(),
888 std::numeric_limits<double>::lowest(),
889 std::numeric_limits<double>::max(),
895 std::numeric_limits<double>::lowest(),
896 std::numeric_limits<double>::max(),
902 std::numeric_limits<double>::lowest(),
903 std::numeric_limits<double>::max(),
909 std::numeric_limits<double>::lowest(),
910 std::numeric_limits<double>::max(),
916 std::numeric_limits<double>::lowest(),
917 std::numeric_limits<double>::max(),
923 std::numeric_limits<double>::lowest(),
924 std::numeric_limits<double>::max(),
930 std::numeric_limits<double>::lowest(),
931 std::numeric_limits<double>::max(),
937 std::numeric_limits<double>::lowest(),
938 std::numeric_limits<double>::max(),
948 std::numeric_limits<double>::lowest(),
949 std::numeric_limits<double>::max(),
955 std::numeric_limits<double>::lowest(),
956 std::numeric_limits<double>::max(),
962 std::numeric_limits<double>::lowest(),
963 std::numeric_limits<double>::max(),
967 indi::addNumberElement<double>(
968 m_indiP_env,
"wind", std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), 0,
"%0.2f" );
970 indi::addNumberElement<double>(
971 m_indiP_env,
"winddir", std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), 0,
"%0.2f" );
975 std::numeric_limits<double>::lowest(),
976 std::numeric_limits<double>::max(),
982 std::numeric_limits<double>::lowest(),
983 std::numeric_limits<double>::max(),
989 std::numeric_limits<double>::lowest(),
990 std::numeric_limits<double>::max(),
996 std::numeric_limits<double>::lowest(),
997 std::numeric_limits<double>::max(),
1003 std::numeric_limits<double>::lowest(),
1004 std::numeric_limits<double>::max(),
1014 std::numeric_limits<unsigned>::lowest(),
1015 std::numeric_limits<unsigned>::max(),
1021 std::numeric_limits<double>::lowest(),
1022 std::numeric_limits<double>::max(),
1028 std::numeric_limits<unsigned>::lowest(),
1029 std::numeric_limits<unsigned>::max(),
1035 std::numeric_limits<double>::lowest(),
1036 std::numeric_limits<double>::max(),
1042 std::numeric_limits<unsigned>::lowest(),
1043 std::numeric_limits<unsigned>::max(),
1049 std::numeric_limits<double>::lowest(),
1050 std::numeric_limits<double>::max(),
1223 std::stringstream
logs;
1327#ifdef LOG_TCS_STATUS
1357#ifdef LOG_TCS_STATUS
1372#ifdef LOG_TCS_STATUS
1400#ifdef LOG_TCS_STATUS
1410 std::vector<std::string>
vres;
1417 pos1 =
tdat.find_first_not_of(
" ", 0 );
1422 pos2 =
tdat.find_first_of(
" ", pos1 );
1426 tok =
tdat.substr( pos1, pos2 - pos1 );
1433 pos2 =
tdat.find_first_not_of(
" ", pos1 );
1438 pos2 =
tdat.find_first_of(
" ", pos1 );
1444 pos2 =
tdat.length();
1446 tok =
tdat.substr( pos1, pos2 - pos1 );
1448 pos2 =
tok.find_first_of(
" \n\r", 0 );
1451 tok.erase( pos2,
tok.length() - pos2 );
1469 if(
en == std::string::npos )
1487 catch(
const std::exception &
e )
1495 x = std::stod(
xstr );
1497 catch(
const std::exception &
e )
1504 if( std::signbit( x ) )
1514 if(
en == std::string::npos )
1532 catch(
const std::exception &
e )
1542 catch(
const std::exception &
e )
1561 catch(
const std::exception &
e )
1571 catch(
const std::exception &
e )
1584 std::vector<std::string>
pdat;
1596 if(
pdat[0] ==
"-1" )
1603 if(
pdat.size() != 3 )
1606 log<text_log>(
"Error getting telescope position (datetime): TCS response wrong size, returned " +
1607 std::to_string(
pdat.size() ) +
" values",
1627 std::vector<std::string>
pdat;
1639 if(
pdat[0] ==
"-1" )
1646 if(
pdat.size() != 6 )
1649 log<text_log>(
"Error getting telescope position (telpos): TCS response wrong size, returned " +
1650 std::to_string(
pdat.size() ) +
" values",
1661 m_telRA = ( h +
m / 60. +
s / 3600. ) * 15.;
1700 std::vector<std::string>
tdat;
1711 if(
tdat[0] ==
"-1" )
1718 if(
tdat.size() != 10 )
1721 log<text_log>(
"[TCS] Error getting telescope data (teldata): TCS response wrong size, returned " +
1722 std::to_string(
tdat.size() ) +
" values",
1730 char bit[2] = { 0, 0 };
1769 std::vector<std::string>
cdat;
1781 if(
cdat[0] ==
"-1" )
1788 if(
cdat.size() != 6 )
1792 if(
cdat.size() == 7 )
1794 if(
cdat[6] ==
"Pointing" )
1803 log<text_log>(
"Catalog data (catdata): TCS response wrong size, returned " +
1804 std::to_string(
cdat.size() ) +
" values",
1807 for(
size_t n = 0;
n <
cdat.size(); ++
n )
1809 std::cerr <<
n <<
" " <<
cdat[
n] <<
"\n";
1833 m_catRA = ( h +
m / 60. +
s / 3600. ) * 15.;
1857 std::vector<std::string>
vedat;
1868 if(
vedat[0] ==
"-1" )
1875 if(
vedat.size() != 10 )
1878 log<text_log>(
"Error getting telescope secondary positions (vedata): TCS response wrong size, returned " +
1879 std::to_string(
vedat.size() ) +
" values",
1906 std::vector<std::string>
edat;
1917 if(
edat[0] ==
"-1" )
1924 if(
edat.size() != 10 )
1927 log<text_log>(
"Error getting telescope environment data (telenv): TCS response wrong size, returned " +
1928 std::to_string(
edat.size() ) +
"values",
1978 int rv =
system(
"query_seeing > /dev/null" );
2003 fin.open(
"/tmp/xsup_query_seeing.txt" );
2203 std::vector<std::string>( {
"epoch",
"ra",
"dec",
"el",
"ha",
"am",
"rotoff" } ),
2283 std::vector<std::string>( {
"object",
"rotmode" } ),
2319 std::vector<std::string>( {
"ra",
"dec",
"epoch",
"rotoff" } ),
2582 static double lastRA = 0;
2584 static double lastEl = 0;
2585 static double lastHA = 0;
2586 static double lastAM = 0;
2613 static double lastAz = 0;
2614 static double lastZd = 0;
2615 static double lastPA = 0;
2794 if( x != 0 || y != 0 )
3041 pcf::IndiProperty
ip( pcf::IndiProperty::Number );
3042 ip.setDevice(
"modwfs" );
3043 ip.setName(
"offset12" );
3044 ip.add( pcf::IndiElement(
"dC1" ) );
3045 ip.add( pcf::IndiElement(
"dC2" ) );
3113 if( !
ipRecv.find(
"toggle" ) )
3115 return log<
software_error, -1>( { __FILE__, __LINE__,
"no toggle element" } );
3120 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3129 if( m_labMode == labMode )
3134 m_labMode = labMode;
3139 updateSwitchIfChanged( m_indiP_labMode,
"toggle", pcf::IndiElement::On,
INDI_OK );
3144 updateSwitchIfChanged( m_indiP_labMode,
"toggle", pcf::IndiElement::Off,
INDI_OK );
3160 x =
ipRecv[
"y"].get<
float>();
3165 y =
ipRecv[
"x"].get<
float>();
3170 z =
ipRecv[
"z"].get<
float>();
3173 return sendPyrNudge( x, y, z );
3180 if( !
ipRecv.find(
"request" ) )
3185 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
3187 return acquireFromGuider();
3197 if( !
ipRecv.find(
"toggle" ) )
3200 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3216 if( m_loopState != 2 )
3219 size_t nextReq = m_lastRequest + 1;
3221 if( nextReq >= m_offloadRequests[0].size() )
3225 float tt0 =
ipRecv[
"00"].get<
float>();
3226 float tt1 =
ipRecv[
"01"].get<
float>();
3230 m_offloadRequests[0][nextReq] = m_lab_offlTT_C_00 * tt0 + m_lab_offlTT_C_01 * tt1;
3231 m_offloadRequests[1][nextReq] = m_lab_offlTT_C_10 * tt0 + m_lab_offlTT_C_11 * tt1;
3235 m_offloadRequests[0][nextReq] = m_offlTT_C_00 * tt0 + m_offlTT_C_01 * tt1;
3236 m_offloadRequests[1][nextReq] = m_offlTT_C_10 * tt0 + m_offlTT_C_11 * tt1;
3240 float f0 =
ipRecv[
"02"].get<
float>();
3242 m_offloadRequests[2][nextReq] = m_offlCFocus_00 * f0;
3245 float c0 =
ipRecv[
"03"].get<
float>();
3246 float c1 =
ipRecv[
"04"].get<
float>();
3248 m_offloadRequests[3][nextReq] = m_offlCComa_00 * c0 + m_offlCComa_01 * c1;
3249 m_offloadRequests[4][nextReq] = m_offlCComa_10 * c0 + m_offlCComa_11 * c1;
3252 m_lastRequest = nextReq;
3254 if( m_nRequests > m_offloadRequests[0].size() )
3256 if( m_firstRequest >= m_offloadRequests[0].size() )
3265 if(
ipRecv.getName() != m_indiP_offlTTenable.getName() )
3267 log<software_error>( { __FILE__, __LINE__,
"wrong INDI property received." } );
3271 if( !
ipRecv.find(
"toggle" ) )
3274 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On && m_offlTT_enabled ==
false )
3276 updateSwitchIfChanged( m_indiP_offlTTenable,
"toggle", pcf::IndiElement::On,
INDI_OK );
3278 m_offlTT_enabled =
true;
3280 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off && m_offlTT_enabled ==
true )
3282 updateSwitchIfChanged( m_indiP_offlTTenable,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
3284 m_offlTT_enabled =
false;
3294 if( !
ipRecv.find(
"request" ) )
3297 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
3299 updateSwitchIfChanged( m_indiP_offlTTdump,
"request", pcf::IndiElement::On,
INDI_OK );
3301 m_offlTT_dump =
true;
3313 if( indiTargetUpdate( m_indiP_offlTTavgInt, target,
ipRecv,
true ) < 0 )
3315 log<software_error>( { __FILE__, __LINE__ } );
3319 m_offlTT_avgInt = target;
3330 if( indiTargetUpdate( m_indiP_offlTTgain, target,
ipRecv,
true ) < 0 )
3332 log<software_error>( { __FILE__, __LINE__ } );
3336 m_offlTT_gain = target;
3347 if( indiTargetUpdate( m_indiP_offlTTthresh, target,
ipRecv,
true ) < 0 )
3349 log<software_error>( { __FILE__, __LINE__ } );
3353 m_offlTT_thresh = target;
3362 if( !
ipRecv.find(
"toggle" ) )
3365 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On && m_offlF_enabled ==
false )
3367 updateSwitchIfChanged( m_indiP_offlFenable,
"toggle", pcf::IndiElement::On,
INDI_OK );
3369 m_offlF_enabled =
true;
3371 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off && m_offlF_enabled ==
true )
3373 updateSwitchIfChanged( m_indiP_offlFenable,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
3375 m_offlF_enabled =
false;
3385 if( !
ipRecv.find(
"request" ) )
3388 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
3390 updateSwitchIfChanged( m_indiP_offlFdump,
"request", pcf::IndiElement::On,
INDI_OK );
3392 m_offlF_dump =
true;
3404 if( indiTargetUpdate( m_indiP_offlFavgInt, target,
ipRecv,
true ) < 0 )
3406 log<software_error>( { __FILE__, __LINE__ } );
3410 m_offlF_avgInt = target;
3421 if( indiTargetUpdate( m_indiP_offlFgain, target,
ipRecv,
true ) < 0 )
3423 log<software_error>( { __FILE__, __LINE__ } );
3427 m_offlF_gain = target;
3438 std::cerr <<
"Got offl thresh\n";
3440 if( indiTargetUpdate( m_indiP_offlFthresh, target,
ipRecv,
true ) < 0 )
3442 log<software_error>( { __FILE__, __LINE__ } );
3446 m_offlF_thresh = target;
The base-class for XWCTk applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
int createStandardIndiRequestSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single request element.
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
int createStandardIndiNumber(pcf::IndiProperty &prop, const std::string &name, const T &min, const T &max, const T &step, const std::string &format, const std::string &label="", const std::string &group="")
Create a standard R/W INDI Number property with target and current elements.
int shutdown()
Get the value of the shutdown flag.
indiDriver< MagAOXApp > * m_indiDriver
The INDI driver wrapper. Constructed and initialized by execute, which starts and stops communication...
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
int createROIndiText(pcf::IndiProperty &prop, const std::string &propName, const std::string &elName, const std::string &propLabel="", const std::string &propGroup="", const std::string &elLabel="")
Create a standard ReadOnly INDI Text property, with at least one element.
int threadStart(std::thread &thrd, bool &thrdInit, pid_t &tpid, pcf::IndiProperty &thProp, int thrdPrio, const std::string &cpuset, const std::string &thrdName, thisPtr *thrdThis, Function &&thrdStart)
Start a thread, using this class's privileges to set priority, etc.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
The MagAO-X Clay Telescope TCS Interface.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlFgain)
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlTTgain)
double m_dimm_el
DIMM elevation at time of seeing measurement.
pcf::IndiProperty m_indiP_offlTTdump
double m_wxdewpoint
Dew point from weather station.
int recordTelem(const telem_telpos *)
virtual int appLogic()
Implementation of the FSM for tcsInterface.
pcf::IndiProperty m_indiP_offlFgain
pcf::IndiProperty m_indiP_acqFromGuider
Property used to request a pyramid nudge.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlTTthresh)
~tcsInterface() noexcept
D'tor, declared and defined for noexcept.
pcf::IndiProperty m_indiP_seeing
INDI Property for seeing.
double m_telDomeAz
dome azimuth
int m_telGuiding
guider moving state
int sendMagTelCommand(const std::string &command, int timeout)
int recordTelCat(bool force=false)
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlFavgInt)
double m_catRA
Catalog right ascension [degrees].
pcf::IndiProperty m_indiP_teltime
double m_dimm_fwhm_corr
DIMM elevation corrected FWHM.
pcf::IndiProperty m_indiP_labMode
int m_telGuiderMoving
guider moving state
pcf::IndiProperty m_indiP_env
INDI Property for environment.
int sendTToffload(float TT_0, float TT_1)
pcf::IndiProperty m_indiP_pyrNudge
Property used to request a pyramid nudge.
int recordTelPos(bool force=false)
int recordTelEnv(bool force=false)
pcf::IndiProperty m_indiP_telpos
int recordTelData(bool force=false)
double m_telPA
parallactic angle
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlTTenable)
double m_wxpres
Outside pressue, millibars.
std::string m_catObj
Catalog object name.
int m_mag2_time
Seconds since midnight of MAG2 measurement.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlFthresh)
pcf::IndiProperty m_indiP_offloadCoeffs
Property used to report the latest woofer modal coefficients for offloading.
pcf::IndiProperty m_offloadThreadProp
Offload thread INDI property.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_pyrNudge)
pcf::IndiProperty m_indiP_offlTTgain
pcf::IndiProperty m_indiP_catdata
INDI Property for the catalog data.
bool m_offloadThreadInit
Initialization flag for the offload thread.
int m_mag1_time
Seconds since midnight of MAG1 measurement.
std::thread m_offloadThread
The offloading thread.
double m_telZd
zenith distance
friend class tcsInterface_test
void offloadThreadExec()
Offload thread function.
int getMagTelStatus(std::string &response, const std::string &statreq)
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlFdump)
virtual void loadConfig()
double m_catDec
Catalog declination [degrees].
double m_wxwind
outside wind intensity, mph
pcf::IndiProperty m_indiP_teldata
int parse_xms(double &x, double &m, double &s, const std::string &xmsstr)
int m_devicePort
The IP port for TCS communications. Should be the command port. Default is 5811.
std::mutex m_tcsMutex
Mutex for locking TCS communications.
double m_mag2_fwhm_corr
MAG2 elevation corrected FWHM.
double m_tcell
Primary mirror cell temperature, Celsius.
double m_mag1_fwhm_corr
MAG1 elevation corrected FWHM.
virtual void setupConfig()
std::string m_deviceAddr
The IP address or resolvable name of the TCS.
pid_t m_offloadThreadID
Offload thread pid.
pcf::IndiProperty m_indiP_vaneend
INDI Property for the vane end positions.
std::string m_catRm
Catalog rotator mode.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_acqFromGuider)
pcf::IndiProperty m_indiP_offlFenable
INDI_SETCALLBACK_DECL(tcsInterface, m_indiP_offloadCoeffs)
int m_dimm_time
Seconds since midnight of DIMM measurement.
pcf::IndiProperty m_indiP_offlFdump
double m_catEp
Catalog epoch.
double m_tambient
Dome air temperature, Celsius.
int getSeeing()
Query, parse, and record seeing measurements.
tcsInterface()
Default c'tor.
int sendFoffload(float F_0)
int badSeeing()
Record bad seeing measurements on errors in getSeeing().
pcf::IndiProperty m_indiP_offlTTenable
double m_ttruss
Telescope truss temperature, Celsius.
int doTToffload(float TT_0, float TT_1)
pcf::IndiProperty m_indiP_catalog
INDI Property for the catalog text information.
double m_wxhumid
Outside humidity, percent.
virtual int appStartup()
Startup function.
int recordTelVane(bool force=false)
virtual int appShutdown()
Shutdown the app.
int recordTelSee(bool force=false)
int doFoffload(float F_0)
int m_telDomeStat
dome status
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
int m_telSlewing
slewing state
int m_telROI
The rotator of interest.
int m_telTracking
tracking state
double m_catRo
Catalog rotator offset.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlFenable)
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_labMode)
double m_wxtemp
Outside temperature, Celsius.
pcf::IndiProperty m_indiP_offlTTavgInt
static void offloadThreadStart(tcsInterface *t)
Offload thread starter function.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlTTdump)
pcf::IndiProperty m_indiP_loopState
Property used to report the loop state.
INDI_NEWCALLBACK_DECL(tcsInterface, m_indiP_offlTTavgInt)
double m_wxwdir
outside wind direction, degrees
double m_tseccell
Secondary mirror cell temperature, Celsius.
pcf::IndiProperty m_indiP_offlFavgInt
std::vector< std::string > parse_teldata(std::string &tdat)
pcf::IndiProperty m_indiP_offlFthresh
pcf::IndiProperty m_indiP_offlTTthresh
std::vector< std::vector< float > > m_offloadRequests
int sendPyrNudge(float x, float y, float z)
INDI_SETCALLBACK_DECL(tcsInterface, m_indiP_loopState)
m_regCounter resize(m_numModes)
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define CREATE_REG_INDI_NEW_TOGGLESWITCH(prop, name)
Create and register a NEW INDI property as a standard toggle switch, using the standard callback name...
#define REG_INDI_NEWPROP(prop, propName, type)
Register a NEW INDI property with the class, using the standard callback name.
#define INDI_SETCALLBACK_DEFN(class, prop)
Define the callback for a set property request.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
const pcf::IndiProperty & ipRecv
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
#define NETSERIAL_E_NOERROR
An input/output capable device.
int loadConfig(mx::app::appConfigurator &config)
Load the device section from an application configurator.
int appStartup()
Perform application startup steps specific to an ioDevice.
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the device section.
unsigned m_readTimeout
The read timeout [msec].
A device base class which saves telemetry.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
Log entry recording the build-time git state.
Log entry recording the build-time git state.
Log entry recording the build-time git state.
Log entry recording the build-time git state.
Log entry recording the build-time git state.
Log entry recording the build-time git state.
Manage a connectio to a serial device over a network.
int serialOut(const char *buf, int len)
int serialInString(char *buf, int len, int timeout, char terminator)
int serialInit(const char *address, int port)