14#include <unordered_map>
17#include <mx/app/application.hpp>
19#include "../MagAOXApp.hpp"
28#define CAMCTRL_E_NOCONFIGS ( -10 )
55 if( value.size() == 0 )
60 size_t first = value.find_first_not_of(
" \t\r\n" );
61 if( first == std::string::npos )
67 size_t last = value.find_last_not_of(
" \t\r\n" );
68 value = value.substr( first, last - first + 1 );
70 if( value.size() >= 2 && value.front() ==
'\"' && value.back() ==
'\"' )
72 value = value.substr( 1, value.size() - 2 );
78 mx::app::appConfigurator &config
82template <
class derivedT,
class =
void>
88template <
class derivedT>
90 : std::bool_constant<derivedT::c_stdCamera_fanSpeed>
95template <
class derivedT,
class =
void>
101template <
class derivedT>
103 : std::bool_constant<derivedT::c_stdCamera_led>
108template <
class derivedT,
class =
void>
114template <
class derivedT>
116 : std::bool_constant<derivedT::c_stdCamera_analogGain>
121template <
class derivedT,
class =
void>
127template <
class derivedT>
129 : std::bool_constant<derivedT::c_stdCamera_hasFocus>
454template <
class derivedT>
551 float m_maxFPS{ std::numeric_limits<float>::max() };
769 std::vector<std::string>
772 std::vector<pcf::IndiProperty>
931 const pcf::IndiProperty &
ipRecv
941 const pcf::IndiProperty &
ipRecv );
961 const pcf::IndiProperty &
ipRecv );
981 const pcf::IndiProperty &
ipRecv );
1001 const pcf::IndiProperty &
ipRecv );
1021 const pcf::IndiProperty &
ipRecv );
1041 const pcf::IndiProperty &
ipRecv );
1061 const pcf::IndiProperty &
ipRecv );
1067 int setFPS( const mx::meta::trueFalseT<true> &t );
1073 int setFPS( const mx::meta::trueFalseT<false> &f );
1081 const pcf::IndiProperty &
ipRecv );
1101 const pcf::IndiProperty &
ipRecv );
1121 const pcf::IndiProperty &
ipRecv );
1127 int setLED( const mx::meta::trueFalseT<true> &t );
1133 int setLED( const mx::meta::trueFalseT<false> &f );
1141 const pcf::IndiProperty &
ipRecv );
1161 const pcf::IndiProperty &
ipRecv );
1169 const pcf::IndiProperty &
ipRecv );
1177 const pcf::IndiProperty &
ipRecv );
1197 const pcf::IndiProperty &
ipRecv );
1205 const pcf::IndiProperty &
ipRecv );
1213 const pcf::IndiProperty &
ipRecv );
1221 const pcf::IndiProperty &
ipRecv );
1229 const pcf::IndiProperty &
ipRecv );
1237 const pcf::IndiProperty &
ipRecv );
1245 const pcf::IndiProperty &
ipRecv );
1265 const pcf::IndiProperty &
ipRecv );
1285 const pcf::IndiProperty &
ipRecv );
1293 const pcf::IndiProperty &
ipRecv );
1301 const pcf::IndiProperty &
ipRecv );
1309 const pcf::IndiProperty &
ipRecv );
1317 const pcf::IndiProperty &
ipRecv );
1325 const pcf::IndiProperty &
ipRecv );
1345 const pcf::IndiProperty &
ipRecv );
1361 const pcf::IndiProperty &
ipRecv );
1366 const pcf::IndiProperty &
ipRecv
1371 const pcf::IndiProperty &
ipRecv );
1419 return *
static_cast<derivedT *
>( this );
1423template <
class derivedT>
1429template <
class derivedT>
1432 if( derivedT::c_stdCamera_tempControl )
1434 config.add(
"camera.startupTemp",
1436 "camera.startupTemp",
1442 "The temperature setpoint to set after a power-on [C]. Default is 20 C." );
1445 if( derivedT::c_stdCamera_readoutSpeed )
1447 config.add(
"camera.defaultReadoutSpeed",
1449 "camera.defaultReadoutSpeed",
1452 "defaultReadoutSpeed",
1455 "The default amplifier and readout speed." );
1458 if( derivedT::c_stdCamera_vShiftSpeed )
1460 config.add(
"camera.defaultVShiftSpeed",
1462 "camera.defaultVShiftSpeed",
1465 "defaultVShiftSpeed",
1468 "The default vertical shift speed." );
1473 config.add(
"camera.fanSpeedControl",
1475 "camera.fanSpeedControl",
1481 "Whether or not fan-speed control is exposed." );
1486 std::string fanSpeedHelp =
"The default fan speed. Must be one of the configured fan-control option names.";
1488 if( !m_fanSpeedNames.empty() )
1490 fanSpeedHelp =
"The default fan speed. Must be one of ";
1492 for(
size_t n = 0; n < m_fanSpeedNames.size(); ++n )
1496 fanSpeedHelp +=
", ";
1499 fanSpeedHelp += m_fanSpeedNames[n];
1502 fanSpeedHelp +=
".";
1505 config.add(
"camera.defaultFanSpeed",
1507 "camera.defaultFanSpeed",
1518 config.add(
"camera.startupLED",
1520 "camera.startupLED",
1526 "Whether or not the status LED is turned on after power on." );
1529 if( derivedT::c_stdCamera_emGain )
1531 config.add(
"camera.maxEMGain",
1539 "The maximum EM gain which can be set by the user." );
1542 if( derivedT::c_stdCamera_usesModes )
1544 config.add(
"camera.startupMode",
1546 "camera.startupMode",
1552 "The mode to set upon power on or application startup." );
1555 if( derivedT::c_stdCamera_usesROI )
1557 config.add(
"camera.default_x",
1565 "The default ROI x position." );
1567 config.add(
"camera.default_y",
1575 "The default ROI y position." );
1577 config.add(
"camera.default_w",
1585 "The default ROI width." );
1587 config.add(
"camera.default_h",
1595 "The default ROI height." );
1597 config.add(
"camera.default_bin_x",
1599 "camera.default_bin_x",
1605 "The default ROI x binning." );
1607 config.add(
"camera.default_bin_y",
1609 "camera.default_bin_y",
1615 "The default ROI y binning." );
1620 config.add(
"focus.stateProperty",
1622 "focus.stateProperty",
1628 "The INDI key (device.property) of a switch property whose configured element is used to infer "
1629 "whether the camera is in focus." );
1631 config.add(
"focus.stateElement",
1633 "focus.stateElement",
1639 "The element of focus.stateProperty whose state is interpreted as focus state. Default is "
1642 config.add(
"focus.stateElementOnMeansInFocus",
1644 "focus.stateElementOnMeansInFocus",
1647 "stateElementOnMeansInFocus",
1650 "Set true when the configured focus.stateElement being On means the camera is in focus. The "
1651 "default false keeps the original behavior where On means out of focus." );
1653 config.add(
"focus.gotoFocus.numSwitches",
1655 "focus.gotoFocus.numSwitches",
1661 "The number of source switch properties combined to derive the goto-focus preset name. Also "
1662 "configure focus.gotoFocus.property1..propertyN, focus.gotoFocus.format, and "
1663 "focus.gotoFocus.targetProperty." );
1665 config.add(
"focus.gotoFocus.format",
1667 "focus.gotoFocus.format",
1673 "Literal {} placeholder format used to combine the configured goto-focus source switch names." );
1675 config.add(
"focus.gotoFocus.targetProperty",
1677 "focus.gotoFocus.targetProperty",
1683 "The INDI key (device.property) of the switch property commanded by gotoFocus()." );
1689template <
class derivedT>
1692 if( derivedT::c_stdCamera_tempControl )
1694 config( m_startupTemp,
"camera.startupTemp" );
1697 if( derivedT::c_stdCamera_readoutSpeed )
1699 config( m_defaultReadoutSpeed,
"camera.defaultReadoutSpeed" );
1702 if( derivedT::c_stdCamera_vShiftSpeed )
1704 config( m_defaultVShiftSpeed,
"camera.defaultVShiftSpeed" );
1709 m_fanSpeedControlEnabled =
true;
1710 config( m_fanSpeedControlEnabled,
"camera.fanSpeedControl" );
1711 config( m_defaultFanSpeed,
"camera.defaultFanSpeed" );
1713 bool fanSpeedValid =
false;
1715 for(
size_t n = 0; n < m_fanSpeedNames.size(); ++n )
1717 if( m_defaultFanSpeed == m_fanSpeedNames[n] )
1719 fanSpeedValid =
true;
1724 if( !fanSpeedValid )
1726 std::string allowedFanSpeeds;
1728 if( m_fanSpeedNames.empty() )
1730 allowedFanSpeeds =
"<none configured>";
1734 for(
size_t n = 0; n < m_fanSpeedNames.size(); ++n )
1738 allowedFanSpeeds +=
", ";
1741 allowedFanSpeeds += m_fanSpeedNames[n];
1747 "invalid camera.defaultFanSpeed: '" +
1748 m_defaultFanSpeed +
"'. Must be one of " +
1749 allowedFanSpeeds +
"." } );
1755 config( m_defaultLEDState,
"camera.startupLED" );
1758 if( derivedT::c_stdCamera_emGain )
1760 config( m_maxEMGain,
"camera.maxEMGain" );
1763 if( derivedT::c_stdCamera_usesModes )
1775 config( m_startupMode,
"camera.startupMode" );
1778 if( derivedT::c_stdCamera_usesROI )
1780 config( m_full_x,
"camera.full_x" );
1781 config( m_full_y,
"camera.full_y" );
1782 config( m_full_w,
"camera.full_w" );
1783 config( m_full_h,
"camera.full_h" );
1784 config( m_full_bin_x,
"camera.full_bin_x" );
1785 config( m_full_bin_y,
"camera.full_bin_y" );
1790 { __FILE__, __LINE__,
"full ROI x (camera.full_x) not set" } );
1796 { __FILE__, __LINE__,
"full ROI y (camera.full_y) not set" } );
1802 { __FILE__, __LINE__,
"full ROI w (camera.full_w) not set" } );
1808 { __FILE__, __LINE__,
"full ROI h (camera.full_h) not set" } );
1811 if( m_full_bin_x < 1 )
1814 { __FILE__, __LINE__,
"full ROI bin-x (camera.full_bin_x) not set" } );
1817 if( m_full_bin_y < 1 )
1820 { __FILE__, __LINE__,
"full ROI bin-y (camera.full_bin_y) not set" } );
1823 config( m_default_x,
"camera.default_x" );
1824 config( m_default_y,
"camera.default_y" );
1825 config( m_default_w,
"camera.default_w" );
1826 config( m_default_h,
"camera.default_h" );
1827 config( m_default_bin_x,
"camera.default_bin_x" );
1828 config( m_default_bin_y,
"camera.default_bin_y" );
1831 if( m_default_x == 0 ) m_default_x = m_full_x;
1832 if( m_default_y == 0 ) m_default_y = m_full_y;
1833 if( m_default_w == 0 ) m_default_w = m_full_w;
1834 if( m_default_h == 0 ) m_default_h = m_full_h;
1835 if( m_default_bin_x < 1 ) m_default_bin_x = m_full_bin_x;
1836 if( m_default_bin_y < 1 ) m_default_bin_y = m_full_bin_y;
1840 m_currentROI.x = m_default_x;
1841 m_currentROI.y = m_default_y;
1842 m_currentROI.w = m_default_w;
1843 m_currentROI.h = m_default_h;
1844 m_currentROI.bin_x = m_default_bin_x;
1845 m_currentROI.bin_y = m_default_bin_y;
1847 m_nextROI.x = m_default_x;
1848 m_nextROI.y = m_default_y;
1849 m_nextROI.w = m_default_w;
1850 m_nextROI.h = m_default_h;
1851 m_nextROI.bin_x = m_default_bin_x;
1852 m_nextROI.bin_y = m_default_bin_y;
1857 config( m_focusStateSource,
"focus.stateProperty" );
1858 config( m_focusStateElement,
"focus.stateElement" );
1859 config( m_focusStateOnMeansInFocus,
"focus.stateElementOnMeansInFocus" );
1860 if( m_focusStateElement ==
"" )
1862 m_focusStateElement =
"toggle";
1865 m_focusStateHelperConfigured =
false;
1866 m_focusStateSourceIndex = -1;
1867 m_focusGotoHelperConfigured =
false;
1868 m_focusGotoSourceProperties.clear();
1869 m_focusGotoSourceIndices.clear();
1870 m_focusGotoFormat.clear();
1871 m_focusGotoTargetProperty.clear();
1872 m_focusGotoTargetDevice.clear();
1873 m_focusGotoTargetName.clear();
1874 m_focusMonitoredPropertyKeys.clear();
1875 m_indiP_focusMonitoredProperties.clear();
1877 auto addFocusMonitoredProperty = [&](
const std::string &propertyKey ) ->
int
1879 for(
size_t n = 0; n < m_focusMonitoredPropertyKeys.size(); ++n )
1881 if( m_focusMonitoredPropertyKeys[n] == propertyKey )
1883 return static_cast<int>( n );
1887 std::string devName;
1888 std::string propName;
1894 m_focusMonitoredPropertyKeys.push_back( propertyKey );
1895 m_indiP_focusMonitoredProperties.emplace_back();
1896 return static_cast<int>( m_focusMonitoredPropertyKeys.size() - 1 );
1899 if( m_focusStateSource !=
"" )
1901 m_focusStateSourceIndex = addFocusMonitoredProperty( m_focusStateSource );
1902 if( m_focusStateSourceIndex < 0 )
1905 { __FILE__, __LINE__,
"invalid focus.stateProperty: " + m_focusStateSource } );
1908 m_focusStateHelperConfigured =
true;
1911 int numFocusGotoSwitches = 0;
1912 config( numFocusGotoSwitches,
"focus.gotoFocus.numSwitches" );
1913 config( m_focusGotoFormat,
"focus.gotoFocus.format" );
1915 config( m_focusGotoTargetProperty,
"focus.gotoFocus.targetProperty" );
1917 bool focusGotoConfigPresent =
1918 numFocusGotoSwitches > 0 || m_focusGotoFormat !=
"" || m_focusGotoTargetProperty !=
"";
1920 if( focusGotoConfigPresent )
1922 if( numFocusGotoSwitches < 1 )
1925 { __FILE__, __LINE__,
"focus.gotoFocus.numSwitches must be greater than zero" } );
1928 if( m_focusGotoFormat ==
"" )
1931 { __FILE__, __LINE__,
"focus.gotoFocus.format must be set when goto-focus helper is used" } );
1934 if( m_focusGotoTargetProperty ==
"" )
1939 "focus.gotoFocus.targetProperty must be set when goto-focus helper is used" } );
1942 bool invalidBraces =
false;
1943 size_t placeholders = 0;
1944 for(
size_t n = 0; n < m_focusGotoFormat.size(); ++n )
1946 if( m_focusGotoFormat[n] ==
'{' )
1948 if( n + 1 < m_focusGotoFormat.size() && m_focusGotoFormat[n + 1] ==
'}' )
1955 invalidBraces =
true;
1959 else if( m_focusGotoFormat[n] ==
'}' )
1961 invalidBraces =
true;
1969 { __FILE__, __LINE__,
"focus.gotoFocus.format only supports literal {} placeholders" } );
1972 if( placeholders !=
static_cast<size_t>( numFocusGotoSwitches ) )
1977 "focus.gotoFocus.format placeholder count does not match focus.gotoFocus.numSwitches" } );
1980 if(
indi::parseIndiKey( m_focusGotoTargetDevice, m_focusGotoTargetName, m_focusGotoTargetProperty ) < 0 )
1983 { __FILE__, __LINE__,
"invalid focus.gotoFocus.targetProperty: " + m_focusGotoTargetProperty } );
1986 for(
int n = 0; n < numFocusGotoSwitches; ++n )
1988 std::string propKey = std::string(
"property" ) + std::to_string( n + 1 );
1989 std::string property;
1990 config.configUnused( property, mx::app::iniFile::makeKey(
"focus.gotoFocus", propKey ) );
1992 if( property ==
"" )
1995 { __FILE__, __LINE__,
"focus.gotoFocus." + propKey +
" must be set" } );
1998 int propertyIndex = addFocusMonitoredProperty( property );
1999 if( propertyIndex < 0 )
2002 { __FILE__, __LINE__,
"invalid focus.gotoFocus." + propKey +
": " +
property } );
2005 m_focusGotoSourceProperties.push_back( property );
2006 m_focusGotoSourceIndices.push_back( propertyIndex );
2009 m_focusGotoHelperConfigured =
true;
2012 if( !m_hasFocus && m_focusStateHelperConfigured && m_focusGotoHelperConfigured )
2021template <
class derivedT>
2024 if( !m_focusStateHelperConfigured || m_focusStateSourceIndex < 0 ||
2025 m_focusStateSourceIndex >=
static_cast<int>( m_indiP_focusMonitoredProperties.size() ) )
2030 const pcf::IndiProperty &focusProperty = m_indiP_focusMonitoredProperties[m_focusStateSourceIndex];
2031 if( !focusProperty.find( m_focusStateElement ) )
2036 if( m_focusStateOnMeansInFocus )
2038 return focusProperty[m_focusStateElement].getSwitchState() == pcf::IndiElement::On;
2041 return focusProperty[m_focusStateElement].getSwitchState() != pcf::IndiElement::On;
2044template <
class derivedT>
2047 if( !( c_hasFocus && m_hasFocus ) || !m_indiP_focus.find(
"state" ) )
2052 mx::meta::trueFalseT<c_hasFocus> tf;
2053 bool inFocus = checkFocus( tf );
2055 pcf::IndiElement::SwitchStateType focusState = pcf::IndiElement::Off;
2056 pcf::IndiProperty::PropertyStateType indiState =
INDI_IDLE;
2060 focusState = pcf::IndiElement::On;
2064 if( derived().m_indiDriver )
2066 derived().updateSwitchIfChanged( m_indiP_focus,
"state", focusState, indiState );
2070 m_indiP_focus[
"state"].setSwitchState( focusState );
2071 m_indiP_focus.setState( indiState );
2074template <
class derivedT>
2077 if( !m_focusGotoHelperConfigured )
2080 { __FILE__, __LINE__,
"goto-focus helper is not configured" } );
2083 std::vector<std::string> activeNames;
2084 activeNames.reserve( m_focusGotoSourceIndices.size() );
2086 for(
size_t n = 0; n < m_focusGotoSourceIndices.size(); ++n )
2088 int propertyIndex = m_focusGotoSourceIndices[n];
2089 if( propertyIndex < 0 || propertyIndex >=
static_cast<int>( m_indiP_focusMonitoredProperties.size() ) )
2092 { __FILE__, __LINE__,
"goto-focus helper property index is out of range" } );
2095 const pcf::IndiProperty &sourceProperty = m_indiP_focusMonitoredProperties[propertyIndex];
2098 std::string activeName;
2099 for(
auto &&el : sourceProperty.getElements() )
2101 if( el.second.getSwitchState() == pcf::IndiElement::On )
2105 activeName = el.first;
2117 "goto-focus helper found no active switch element in " + m_focusGotoSourceProperties[n] } );
2125 "goto-focus helper found multiple active switch elements in " + m_focusGotoSourceProperties[n] } );
2128 activeNames.push_back( activeName );
2131 std::string targetElement;
2132 size_t valueIndex = 0;
2133 for(
size_t n = 0; n < m_focusGotoFormat.size(); ++n )
2135 if( m_focusGotoFormat[n] ==
'{' && n + 1 < m_focusGotoFormat.size() && m_focusGotoFormat[n + 1] ==
'}' )
2137 targetElement += activeNames[valueIndex];
2143 targetElement += m_focusGotoFormat[n];
2147 if( targetElement ==
"" )
2150 { __FILE__, __LINE__,
"goto-focus helper produced an empty target element name" } );
2153 pcf::IndiProperty ipSend( pcf::IndiProperty::Switch );
2154 ipSend.setDevice( m_focusGotoTargetDevice );
2155 ipSend.setName( m_focusGotoTargetName );
2156 ipSend.setRule( pcf::IndiProperty::AtMostOne );
2157 ipSend.add( pcf::IndiElement( targetElement, pcf::IndiElement::On ) );
2159 derivedT::template log<text_log>(
"goto-focus helper commanding " + m_focusGotoTargetProperty +
"." +
2162 return derived().sendNewProperty( ipSend );
2165template <
class derivedT>
2168 static_cast<void>( t );
2170 derived().createStandardIndiSelectionSw(
2171 m_indiP_readoutSpeed,
"readout_speed", m_readoutSpeedNames,
"Readout Speed" );
2174 if( m_readoutSpeedNameLabels.size() == m_readoutSpeedNames.size() )
2176 for(
size_t n = 0; n < m_readoutSpeedNames.size(); ++n )
2177 m_indiP_readoutSpeed[m_readoutSpeedNames[n]].setLabel( m_readoutSpeedNameLabels[n] );
2180 derived().registerIndiPropertyNew( m_indiP_readoutSpeed, st_newCallBack_stdCamera );
2185template <
class derivedT>
2188 static_cast<void>( f );
2193template <
class derivedT>
2196 static_cast<void>( t );
2198 derived().createStandardIndiSelectionSw(
2199 m_indiP_vShiftSpeed,
"vshift_speed", m_vShiftSpeedNames,
"Vert. Shift Speed" );
2201 if( m_vShiftSpeedNameLabels.size() == m_vShiftSpeedNames.size() )
2203 for(
size_t n = 0; n < m_vShiftSpeedNames.size(); ++n )
2204 m_indiP_vShiftSpeed[m_vShiftSpeedNames[n]].setLabel( m_vShiftSpeedNameLabels[n] );
2207 derived().registerIndiPropertyNew( m_indiP_vShiftSpeed, st_newCallBack_stdCamera );
2212template <
class derivedT>
2215 static_cast<void>( f );
2220template <
class derivedT>
2223 static_cast<void>( t );
2225 derived().createStandardIndiSelectionSw( m_indiP_fanSpeed,
"fan_speed", m_fanSpeedNames,
"Fan Speed" );
2227 if( m_fanSpeedNameLabels.size() == m_fanSpeedNames.size() )
2229 for(
size_t n = 0; n < m_fanSpeedNames.size(); ++n )
2231 m_indiP_fanSpeed[m_fanSpeedNames[n]].setLabel( m_fanSpeedNameLabels[n] );
2235 derived().registerIndiPropertyNew( m_indiP_fanSpeed, st_newCallBack_stdCamera );
2240template <
class derivedT>
2243 static_cast<void>( f );
2248template <
class derivedT>
2252 if( derivedT::c_stdCamera_tempControl )
2255 derived().createStandardIndiNumber(
2256 m_indiP_temp,
"temp_ccd", m_minTemp, m_maxTemp, m_stepTemp,
"%0.1f",
"CCD Temperature",
"CCD Temperature" );
2257 m_indiP_temp[
"current"].set( m_ccdTemp );
2258 m_indiP_temp[
"target"].set( m_ccdTempSetpt );
2259 if( derived().registerIndiPropertyNew( m_indiP_temp, st_newCallBack_stdCamera ) < 0 )
2261#ifndef STDCAMERA_TEST_NOLOG
2262 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2267 derived().createStandardIndiToggleSw(
2268 m_indiP_tempcont,
"temp_controller",
"CCD Temperature",
"Control On/Off" );
2269 m_indiP_tempcont[
"toggle"].set( pcf::IndiElement::Off );
2270 if( derived().registerIndiPropertyNew( m_indiP_tempcont, st_newCallBack_stdCamera ) < 0 )
2272#ifndef STDCAMERA_TEST_NOLOG
2273 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2278 derived().createROIndiText(
2279 m_indiP_tempstat,
"temp_control",
"status",
"CCD Temperature",
"",
"CCD Temperature" );
2280 if( derived().registerIndiPropertyReadOnly( m_indiP_tempstat ) < 0 )
2282#ifndef STDCAMERA_TEST_NOLOG
2283 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2288 else if( derivedT::c_stdCamera_temp )
2290 derived().createROIndiNumber( m_indiP_temp,
"temp_ccd",
"CCD Temperature",
"CCD Temperature" );
2291 m_indiP_temp.add( pcf::IndiElement(
"current" ) );
2292 m_indiP_temp[
"current"].set( m_ccdTemp );
2293 if( derived().registerIndiPropertyReadOnly( m_indiP_temp ) < 0 )
2295#ifndef STDCAMERA_TEST_NOLOG
2296 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2302 if( derivedT::c_stdCamera_readoutSpeed )
2304 mx::meta::trueFalseT<derivedT::c_stdCamera_readoutSpeed> tf;
2305 if( createReadoutSpeed( tf ) < 0 )
2307#ifndef STDCAMERA_TEST_NOLOG
2308 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2314 if( derivedT::c_stdCamera_vShiftSpeed )
2316 mx::meta::trueFalseT<derivedT::c_stdCamera_vShiftSpeed> tf;
2317 if( createVShiftSpeed( tf ) < 0 )
2319#ifndef STDCAMERA_TEST_NOLOG
2320 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2326 if( derivedT::c_stdCamera_emGain )
2328 derived().createStandardIndiNumber( m_indiP_emGain,
"emgain", 0, 1000, 1,
"%0.3f" );
2329 if( derived().registerIndiPropertyNew( m_indiP_emGain, st_newCallBack_stdCamera ) < 0 )
2331#ifndef STDCAMERA_TEST_NOLOG
2332 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2338 if( derivedT::c_stdCamera_exptimeCtrl )
2340 derived().createStandardIndiNumber(
2341 m_indiP_exptime,
"exptime", m_minExpTime, m_maxExpTime, m_stepExpTime,
"%0.3f" );
2342 if( derived().registerIndiPropertyNew( m_indiP_exptime, st_newCallBack_stdCamera ) < 0 )
2344#ifndef STDCAMERA_TEST_NOLOG
2345 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2351 if( derivedT::c_stdCamera_fpsCtrl )
2353 derived().createStandardIndiNumber( m_indiP_fps,
"fps", m_minFPS, m_maxFPS, m_stepFPS,
"%0.2f" );
2354 if( derived().registerIndiPropertyNew( m_indiP_fps, st_newCallBack_stdCamera ) < 0 )
2356#ifndef STDCAMERA_TEST_NOLOG
2357 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2362 else if( derivedT::c_stdCamera_fps )
2364 derived().createROIndiNumber( m_indiP_fps,
"fps" );
2365 m_indiP_fps.add( pcf::IndiElement(
"current" ) );
2366 m_indiP_fps[
"current"].setMin( m_minFPS );
2367 m_indiP_fps[
"current"].setMax( m_maxFPS );
2368 m_indiP_fps[
"current"].setStep( m_stepFPS );
2369 m_indiP_fps[
"current"].setFormat(
"%0.2f" );
2371 if( derived().registerIndiPropertyReadOnly( m_indiP_fps ) < 0 )
2373#ifndef STDCAMERA_TEST_NOLOG
2374 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2380 if( c_hasFanSpeed && m_fanSpeedControlEnabled )
2382 if( m_fanSpeedNames.empty() )
2384#ifndef STDCAMERA_TEST_NOLOG
2385 derivedT::template log<software_error>( { __FILE__, __LINE__,
"no fan control options configured" } );
2390 if( m_fanSpeedNameLabels.size() == m_fanSpeedNames.size() )
2392 derived().createStandardIndiSelectionSw(
2393 m_indiP_fanSpeed,
"fan_speed", m_fanSpeedNames, m_fanSpeedNameLabels,
"Fan Speed",
"Fan" );
2397 derived().createStandardIndiSelectionSw(
2398 m_indiP_fanSpeed,
"fan_speed", m_fanSpeedNames,
"Fan Speed",
"Fan" );
2401 if( derived().registerIndiPropertyNew( m_indiP_fanSpeed, st_newCallBack_stdCamera ) < 0 )
2403#ifndef STDCAMERA_TEST_NOLOG
2404 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2410 if( c_hasAnalogGain )
2412 if( m_analogGainNames.empty() )
2414#ifndef STDCAMERA_TEST_NOLOG
2415 derivedT::template log<software_error>( { __FILE__, __LINE__,
"no analog gain options configured" } );
2420 if( m_analogGainNameLabels.size() == m_analogGainNames.size() )
2422 derived().createStandardIndiSelectionSw(
2423 m_indiP_analogGain,
"analog_gain", m_analogGainNames, m_analogGainNameLabels,
"Analog Gain",
"Gain" );
2427 derived().createStandardIndiSelectionSw(
2428 m_indiP_analogGain,
"analog_gain", m_analogGainNames,
"Analog Gain",
"Gain" );
2431 if( derived().registerIndiPropertyNew( m_indiP_analogGain, st_newCallBack_stdCamera ) < 0 )
2433#ifndef STDCAMERA_TEST_NOLOG
2434 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2442 derived().createStandardIndiToggleSw( m_indiP_led,
"led",
"Status LED",
"LED" );
2443 if( derived().registerIndiPropertyNew( m_indiP_led, st_newCallBack_stdCamera ) < 0 )
2445#ifndef STDCAMERA_TEST_NOLOG
2446 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2452 if( derivedT::c_stdCamera_synchro )
2454 derived().createStandardIndiToggleSw( m_indiP_synchro,
"synchro",
"Synchronization",
"Synchronization" );
2455 if( derived().registerIndiPropertyNew( m_indiP_synchro, st_newCallBack_stdCamera ) < 0 )
2457#ifndef STDCAMERA_TEST_NOLOG
2458 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2464 if( derivedT::c_stdCamera_usesModes )
2466 std::vector<std::string> modeNames;
2467 for(
auto it = m_cameraModes.begin();
it != m_cameraModes.end(); ++
it )
2469 modeNames.push_back(
it->first );
2472 if( derived().createStandardIndiSelectionSw( m_indiP_mode,
"mode", modeNames ) < 0 )
2474 derivedT::template log<software_critical>( { __FILE__, __LINE__ } );
2477 if( derived().registerIndiPropertyNew( m_indiP_mode, st_newCallBack_stdCamera ) < 0 )
2479#ifndef STDCAMERA_TEST_NOLOG
2480 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2486 derived().createStandardIndiRequestSw( m_indiP_reconfig,
"reconfigure" );
2487 if( derived().registerIndiPropertyNew( m_indiP_reconfig, st_newCallBack_stdCamera ) < 0 )
2489#ifndef STDCAMERA_TEST_NOLOG
2490 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2495 if( derivedT::c_stdCamera_usesROI )
2498 derived().createStandardIndiNumber( m_indiP_roi_x,
"roi_region_x", m_minROIx, m_maxROIx, m_stepROIx,
"%0.1f" );
2499 if( derived().registerIndiPropertyNew( m_indiP_roi_x, st_newCallBack_stdCamera ) < 0 )
2501#ifndef STDCAMERA_TEST_NOLOG
2502 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2507 derived().createStandardIndiNumber( m_indiP_roi_y,
"roi_region_y", m_minROIy, m_maxROIy, m_stepROIy,
"%0.1f" );
2508 if( derived().registerIndiPropertyNew( m_indiP_roi_y, st_newCallBack_stdCamera ) < 0 )
2510#ifndef STDCAMERA_TEST_NOLOG
2511 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2516 derived().createStandardIndiNumber(
2517 m_indiP_roi_w,
"roi_region_w", m_minROIWidth, m_maxROIWidth, m_stepROIWidth,
"%d" );
2518 if( derived().registerIndiPropertyNew( m_indiP_roi_w, st_newCallBack_stdCamera ) < 0 )
2520#ifndef STDCAMERA_TEST_NOLOG
2521 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2526 derived().createStandardIndiNumber(
2527 m_indiP_roi_h,
"roi_region_h", m_minROIHeight, m_maxROIHeight, m_stepROIHeight,
"%d" );
2528 if( derived().registerIndiPropertyNew( m_indiP_roi_h, st_newCallBack_stdCamera ) < 0 )
2530#ifndef STDCAMERA_TEST_NOLOG
2531 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2536 derived().createStandardIndiNumber(
2537 m_indiP_roi_bin_x,
"roi_region_bin_x", m_minROIBinning_x, m_maxROIBinning_x, m_stepROIBinning_x,
"%f" );
2538 if( derived().registerIndiPropertyNew( m_indiP_roi_bin_x, st_newCallBack_stdCamera ) < 0 )
2540#ifndef STDCAMERA_TEST_NOLOG
2541 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2546 derived().createStandardIndiNumber(
2547 m_indiP_roi_bin_y,
"roi_region_bin_y", m_minROIBinning_y, m_maxROIBinning_y, m_stepROIBinning_y,
"%f" );
2548 if( derived().registerIndiPropertyNew( m_indiP_roi_bin_y, st_newCallBack_stdCamera ) < 0 )
2550#ifndef STDCAMERA_TEST_NOLOG
2551 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2556 derived().createROIndiNumber( m_indiP_fullROI,
"roi_full_region" );
2557 m_indiP_fullROI.add( pcf::IndiElement(
"x" ) );
2558 m_indiP_fullROI[
"x"] = 0;
2559 m_indiP_fullROI.add( pcf::IndiElement(
"y" ) );
2560 m_indiP_fullROI[
"y"] = 0;
2561 m_indiP_fullROI.add( pcf::IndiElement(
"w" ) );
2562 m_indiP_fullROI[
"w"] = 0;
2563 m_indiP_fullROI.add( pcf::IndiElement(
"h" ) );
2564 m_indiP_fullROI[
"h"] = 0;
2565 if( derived().registerIndiPropertyReadOnly( m_indiP_fullROI ) < 0 )
2567#ifndef STDCAMERA_TEST_NOLOG
2568 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2573 derived().createStandardIndiRequestSw( m_indiP_roi_check,
"roi_region_check" );
2574 if( derived().registerIndiPropertyNew( m_indiP_roi_check, st_newCallBack_stdCamera ) < 0 )
2576#ifndef STDCAMERA_TEST_NOLOG
2577 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2582 derived().createStandardIndiRequestSw( m_indiP_roi_set,
"roi_set" );
2583 if( derived().registerIndiPropertyNew( m_indiP_roi_set, st_newCallBack_stdCamera ) < 0 )
2585#ifndef STDCAMERA_TEST_NOLOG
2586 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2591 derived().createStandardIndiRequestSw( m_indiP_roi_full,
"roi_set_full" );
2592 if( derived().registerIndiPropertyNew( m_indiP_roi_full, st_newCallBack_stdCamera ) < 0 )
2594#ifndef STDCAMERA_TEST_NOLOG
2595 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2600 derived().createStandardIndiRequestSw( m_indiP_roi_fullbin,
"roi_set_full_bin" );
2601 if( derived().registerIndiPropertyNew( m_indiP_roi_fullbin, st_newCallBack_stdCamera ) < 0 )
2603#ifndef STDCAMERA_TEST_NOLOG
2604 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2609 derived().createStandardIndiRequestSw( m_indiP_roi_loadlast,
"roi_load_last" );
2610 if( derived().registerIndiPropertyNew( m_indiP_roi_loadlast, st_newCallBack_stdCamera ) < 0 )
2612#ifndef STDCAMERA_TEST_NOLOG
2613 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2618 derived().createStandardIndiRequestSw( m_indiP_roi_last,
"roi_set_last" );
2619 if( derived().registerIndiPropertyNew( m_indiP_roi_last, st_newCallBack_stdCamera ) < 0 )
2621#ifndef STDCAMERA_TEST_NOLOG
2622 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2627 derived().createStandardIndiRequestSw( m_indiP_roi_default,
"roi_set_default" );
2628 if( derived().registerIndiPropertyNew( m_indiP_roi_default, st_newCallBack_stdCamera ) < 0 )
2630#ifndef STDCAMERA_TEST_NOLOG
2631 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2637 if( derivedT::c_stdCamera_cropMode )
2639 derived().createStandardIndiToggleSw( m_indiP_cropMode,
"roi_crop_mode",
"Crop Mode",
"Crop Mode" );
2640 if( derived().registerIndiPropertyNew( m_indiP_cropMode, st_newCallBack_stdCamera ) < 0 )
2642#ifndef STDCAMERA_TEST_NOLOG
2643 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2650 if( derivedT::c_stdCamera_hasShutter )
2652 derived().createROIndiText(
2653 m_indiP_shutterStatus,
"shutter_status",
"status",
"Shutter Status",
"Shutter",
"Status" );
2654 m_indiP_shutterStatus[
"status"] = m_shutterStatus;
2655 if( derived().registerIndiPropertyReadOnly( m_indiP_shutterStatus ) < 0 )
2657#ifndef STDCAMERA_TEST_NOLOG
2658 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2663 derived().createStandardIndiToggleSw( m_indiP_shutter,
"shutter",
"Shutter",
"Shutter" );
2664 if( derived().registerIndiPropertyNew( m_indiP_shutter, st_newCallBack_stdCamera ) < 0 )
2666#ifndef STDCAMERA_TEST_NOLOG
2667 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2673 if( c_hasFocus && m_hasFocus )
2675 m_indiP_focus = pcf::IndiProperty( pcf::IndiProperty::Switch );
2676 m_indiP_focus.setDevice( derived().configName() );
2677 m_indiP_focus.setName(
"focus" );
2678 m_indiP_focus.setPerm( pcf::IndiProperty::ReadOnly );
2679 m_indiP_focus.setState( pcf::IndiProperty::Idle );
2680 m_indiP_focus.setRule( pcf::IndiProperty::AtMostOne );
2681 m_indiP_focus.setLabel(
"Focus" );
2682 m_indiP_focus.setGroup(
"Focus" );
2683 m_indiP_focus.add( pcf::IndiElement(
"state", pcf::IndiElement::Off ) );
2684 if( derived().registerIndiPropertyReadOnly( m_indiP_focus ) < 0 )
2686#ifndef STDCAMERA_TEST_NOLOG
2687 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2692 derived().createStandardIndiRequestSw( m_indiP_gotoFocus,
"goto_focus",
"Goto Focus",
"Focus" );
2693 if( derived().registerIndiPropertyNew( m_indiP_gotoFocus, st_newCallBack_stdCamera ) < 0 )
2695#ifndef STDCAMERA_TEST_NOLOG
2696 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2702 if( c_hasFocus && !m_focusMonitoredPropertyKeys.empty() )
2704 for(
size_t n = 0; n < m_focusMonitoredPropertyKeys.size(); ++n )
2706 std::string devName;
2707 std::string propName;
2710#ifndef STDCAMERA_TEST_NOLOG
2711 derivedT::template log<software_error>(
2712 { __FILE__, __LINE__,
"invalid monitored focus property: " + m_focusMonitoredPropertyKeys[n] } );
2717 if( derived().registerIndiPropertySet(
2718 m_indiP_focusMonitoredProperties[n], devName, propName, st_setCallBack_focusMonitored ) < 0 )
2720#ifndef STDCAMERA_TEST_NOLOG
2721 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2728 if( derivedT::c_stdCamera_usesStateString )
2730 derived().createROIndiText( m_indiP_stateString,
"state_string",
"current",
"State String",
"State",
"String" );
2731 m_indiP_stateString.add( pcf::IndiElement(
"valid" ) );
2732 m_indiP_stateString[
"valid"] =
"no";
2733 if( derived().registerIndiPropertyReadOnly( m_indiP_stateString ) < 0 )
2735#ifndef STDCAMERA_TEST_NOLOG
2736 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
2745template <
class derivedT>
2753 if( derived().powerOnWaitElapsed() )
2757 m_currentROI.x = m_default_x;
2758 m_currentROI.y = m_default_y;
2759 m_currentROI.w = m_default_w;
2760 m_currentROI.h = m_default_h;
2761 m_currentROI.bin_x = m_default_bin_x;
2762 m_currentROI.bin_y = m_default_bin_y;
2764 m_nextROI.x = m_default_x;
2765 m_nextROI.y = m_default_y;
2766 m_nextROI.w = m_default_w;
2767 m_nextROI.h = m_default_h;
2768 m_nextROI.bin_x = m_default_bin_x;
2769 m_nextROI.bin_y = m_default_bin_y;
2772 derived().powerOnDefaults();
2774 if( derivedT::c_stdCamera_tempControl )
2777 if( m_startupTemp > -999 )
2778 m_ccdTempSetpt = m_startupTemp;
2779 derived().updateIfChanged( m_indiP_temp,
"target", m_ccdTempSetpt,
INDI_IDLE );
2782 if( derivedT::c_stdCamera_usesROI )
2785 m_nextROI.x = m_currentROI.x;
2786 m_nextROI.y = m_currentROI.y;
2787 m_nextROI.w = m_currentROI.w;
2788 m_nextROI.h = m_currentROI.h;
2789 m_nextROI.bin_x = m_currentROI.bin_x;
2790 m_nextROI.bin_y = m_currentROI.bin_y;
2792 derived().updateIfChanged( m_indiP_roi_x,
"current", m_currentROI.x,
INDI_IDLE );
2793 derived().updateIfChanged( m_indiP_roi_x,
"target", m_nextROI.x,
INDI_IDLE );
2795 derived().updateIfChanged( m_indiP_roi_y,
"current", m_currentROI.y,
INDI_IDLE );
2796 derived().updateIfChanged( m_indiP_roi_y,
"target", m_nextROI.y,
INDI_IDLE );
2798 derived().updateIfChanged( m_indiP_roi_w,
"current", m_currentROI.w,
INDI_IDLE );
2799 derived().updateIfChanged( m_indiP_roi_w,
"target", m_nextROI.w,
INDI_IDLE );
2801 derived().updateIfChanged( m_indiP_roi_h,
"current", m_currentROI.h,
INDI_IDLE );
2802 derived().updateIfChanged( m_indiP_roi_h,
"target", m_nextROI.h,
INDI_IDLE );
2804 derived().updateIfChanged( m_indiP_roi_bin_x,
"current", m_currentROI.bin_x,
INDI_IDLE );
2805 derived().updateIfChanged( m_indiP_roi_bin_x,
"target", m_nextROI.bin_x,
INDI_IDLE );
2807 derived().updateIfChanged( m_indiP_roi_bin_y,
"current", m_currentROI.bin_y,
INDI_IDLE );
2808 derived().updateIfChanged( m_indiP_roi_bin_y,
"target", m_nextROI.bin_y,
INDI_IDLE );
2811 if( derivedT::c_stdCamera_hasShutter )
2813 if( m_shutterStatus ==
"OPERATING" )
2815 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_BUSY );
2817 if( m_shutterStatus ==
"POWERON" || m_shutterStatus ==
"READY" )
2819 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_OK );
2823 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_IDLE );
2826 if( m_shutterState == 1 )
2828 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::On,
INDI_OK );
2832 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
2836 if( c_hasFocus && m_hasFocus )
2838 updateFocusStateProperty();
2839 derived().updateSwitchIfChanged( m_indiP_gotoFocus,
"request", pcf::IndiElement::Off,
INDI_IDLE );
2851 if( c_hasFanSpeed && m_fanSpeedControlEnabled && m_fanSpeedValid )
2854 m_indiP_fanSpeed, m_fanSpeedName, derived().m_indiDriver,
INDI_IDLE );
2857 if( c_hasAnalogGain && m_analogGainValid )
2860 m_indiP_analogGain, m_analogGainName, derived().m_indiDriver,
INDI_IDLE );
2863 if( c_hasLED && m_ledStateValid )
2867 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::On,
INDI_IDLE );
2871 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
2875 if( derivedT::c_stdCamera_usesROI )
2877 derived().updateIfChanged( m_indiP_roi_x,
"current", m_currentROI.x,
INDI_IDLE );
2878 derived().updateIfChanged( m_indiP_roi_x,
"target", m_nextROI.x,
INDI_IDLE );
2880 derived().updateIfChanged( m_indiP_roi_y,
"current", m_currentROI.y,
INDI_IDLE );
2881 derived().updateIfChanged( m_indiP_roi_y,
"target", m_nextROI.y,
INDI_IDLE );
2883 derived().updateIfChanged( m_indiP_roi_w,
"current", m_currentROI.w,
INDI_IDLE );
2884 derived().updateIfChanged( m_indiP_roi_w,
"target", m_nextROI.w,
INDI_IDLE );
2886 derived().updateIfChanged( m_indiP_roi_h,
"current", m_currentROI.h,
INDI_IDLE );
2887 derived().updateIfChanged( m_indiP_roi_h,
"target", m_nextROI.h,
INDI_IDLE );
2889 derived().updateIfChanged( m_indiP_roi_bin_x,
"current", m_currentROI.bin_x,
INDI_IDLE );
2890 derived().updateIfChanged( m_indiP_roi_bin_x,
"target", m_nextROI.bin_x,
INDI_IDLE );
2892 derived().updateIfChanged( m_indiP_roi_bin_y,
"current", m_currentROI.bin_y,
INDI_IDLE );
2893 derived().updateIfChanged( m_indiP_roi_bin_y,
"target", m_nextROI.bin_y,
INDI_IDLE );
2899 catch(
const std::exception &e )
2902 { __FILE__, __LINE__, std::string(
"Exception caught: " ) + e.what() } );
2906template <
class derivedT>
2909 if( !derived().m_indiDriver )
2914 if( derivedT::c_stdCamera_usesModes )
2916 for(
auto it = m_cameraModes.begin();
it != m_cameraModes.end(); ++
it )
2918 derived().updateSwitchIfChanged( m_indiP_mode,
it->first, pcf::IndiElement::Off,
INDI_IDLE );
2922 if( derivedT::c_stdCamera_usesROI )
2944 m_currentROI.x = m_default_x;
2945 m_currentROI.y = m_default_y;
2946 m_currentROI.w = m_default_w;
2947 m_currentROI.h = m_default_h;
2948 m_currentROI.bin_x = m_default_bin_x;
2949 m_currentROI.bin_y = m_default_bin_y;
2951 m_nextROI.x = m_default_x;
2952 m_nextROI.y = m_default_y;
2953 m_nextROI.w = m_default_w;
2954 m_nextROI.h = m_default_h;
2955 m_nextROI.bin_x = m_default_bin_x;
2956 m_nextROI.bin_y = m_default_bin_y;
2960 if( derivedT::c_stdCamera_hasShutter )
2962 if( m_shutterStatus ==
"OPERATING" )
2964 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_BUSY );
2966 if( m_shutterStatus ==
"POWERON" || m_shutterStatus ==
"READY" )
2968 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_OK );
2972 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_IDLE );
2975 if( m_shutterState == 0 )
2977 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::On,
INDI_OK );
2981 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
2985 if( c_hasFocus && m_hasFocus )
2987 updateFocusStateProperty();
2988 derived().updateSwitchIfChanged( m_indiP_gotoFocus,
"request", pcf::IndiElement::Off,
INDI_IDLE );
2991 if( c_hasFanSpeed && m_fanSpeedControlEnabled && m_fanSpeedValid )
2996 if( c_hasAnalogGain && m_analogGainValid )
3001 if( c_hasLED && m_ledStateValid )
3005 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::On,
INDI_IDLE );
3009 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
3016template <
class derivedT>
3020 if( derivedT::c_stdCamera_hasShutter )
3022 if( m_shutterStatus ==
"OPERATING" )
3024 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_BUSY );
3026 if( m_shutterStatus ==
"POWERON" || m_shutterStatus ==
"READY" )
3028 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_OK );
3032 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_IDLE );
3035 if( m_shutterState == 0 )
3037 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::On,
INDI_OK );
3041 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
3045 if( c_hasFocus && m_hasFocus )
3047 updateFocusStateProperty();
3048 derived().updateSwitchIfChanged( m_indiP_gotoFocus,
"request", pcf::IndiElement::Off,
INDI_IDLE );
3051 if( c_hasFanSpeed && m_fanSpeedControlEnabled && m_fanSpeedValid )
3056 if( c_hasAnalogGain && m_analogGainValid )
3061 if( c_hasLED && m_ledStateValid )
3065 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::On,
INDI_IDLE );
3069 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
3076template <
class derivedT>
3082template <
class derivedT>
3085 derivedT *_app =
static_cast<derivedT *
>( app );
3086 return _app->newCallBack_stdCamera(
ipRecv );
3089template <
class derivedT>
3093 if(
ipRecv.getDevice() != derived().configName() )
3095#ifndef XWCTEST_INDI_CALLBACK_VALIDATION
3096 derivedT::template log<software_error>( { __FILE__, __LINE__,
"unknown INDI property" } );
3102 std::string name =
ipRecv.getName();
3104 if( name ==
"reconfigure" )
3105 return newCallBack_reconfigure(
ipRecv );
3106 else if( derivedT::c_stdCamera_temp && name ==
"temp_ccd" )
3107 return newCallBack_temp(
ipRecv );
3108 else if( derivedT::c_stdCamera_tempControl && name ==
"temp_ccd" )
3109 return newCallBack_temp(
ipRecv );
3110 else if( derivedT::c_stdCamera_tempControl && name ==
"temp_controller" )
3111 return newCallBack_temp_controller(
ipRecv );
3112 else if( derivedT::c_stdCamera_readoutSpeed && name ==
"readout_speed" )
3113 return newCallBack_readoutSpeed(
ipRecv );
3114 else if( derivedT::c_stdCamera_vShiftSpeed && name ==
"vshift_speed" )
3115 return newCallBack_vShiftSpeed(
ipRecv );
3116 else if( derivedT::c_stdCamera_emGain && name ==
"emgain" )
3117 return newCallBack_emgain(
ipRecv );
3118 else if( derivedT::c_stdCamera_exptimeCtrl && name ==
"exptime" )
3119 return newCallBack_exptime(
ipRecv );
3120 else if( derivedT::c_stdCamera_fpsCtrl && name ==
"fps" )
3121 return newCallBack_fps(
ipRecv );
3122 else if( c_hasFanSpeed && m_fanSpeedControlEnabled && name ==
"fan_speed" )
3123 return newCallBack_fanSpeed(
ipRecv );
3124 else if( c_hasAnalogGain && name ==
"analog_gain" )
3125 return newCallBack_analogGain(
ipRecv );
3126 else if( c_hasLED && name ==
"led" )
3127 return newCallBack_led(
ipRecv );
3128 else if( derivedT::c_stdCamera_synchro && name ==
"synchro" )
3129 return newCallBack_synchro(
ipRecv );
3130 else if( derivedT::c_stdCamera_usesModes && name ==
"mode" )
3131 return newCallBack_mode(
ipRecv );
3132 else if( derivedT::c_stdCamera_cropMode && name ==
"roi_crop_mode" )
3133 return newCallBack_cropMode(
ipRecv );
3134 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_x" )
3135 return newCallBack_roi_x(
ipRecv );
3136 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_y" )
3137 return newCallBack_roi_y(
ipRecv );
3138 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_w" )
3139 return newCallBack_roi_w(
ipRecv );
3140 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_h" )
3141 return newCallBack_roi_h(
ipRecv );
3142 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_bin_x" )
3143 return newCallBack_roi_bin_x(
ipRecv );
3144 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_bin_y" )
3145 return newCallBack_roi_bin_y(
ipRecv );
3146 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_region_check" )
3147 return newCallBack_roi_check(
ipRecv );
3148 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_set" )
3149 return newCallBack_roi_set(
ipRecv );
3150 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_set_full" )
3151 return newCallBack_roi_full(
ipRecv );
3152 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_set_full_bin" )
3153 return newCallBack_roi_fullbin(
ipRecv );
3154 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_load_last" )
3155 return newCallBack_roi_loadlast(
ipRecv );
3156 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_set_last" )
3157 return newCallBack_roi_last(
ipRecv );
3158 else if( derivedT::c_stdCamera_usesROI && name ==
"roi_set_default" )
3159 return newCallBack_roi_default(
ipRecv );
3160 else if( derivedT::c_stdCamera_hasShutter && name ==
"shutter" )
3161 return newCallBack_shutter(
ipRecv );
3162 else if( c_hasFocus && m_hasFocus && name ==
"goto_focus" )
3163 return newCallBack_gotoFocus(
ipRecv );
3165#ifndef XWCTEST_INDI_CALLBACK_VALIDATION
3166 derivedT::template log<software_error>( { __FILE__, __LINE__,
"unknown INDI property" } );
3172template <
class derivedT>
3175 static_cast<void>( t );
3176 return derived().setTempSetPt();
3179template <
class derivedT>
3182 static_cast<void>( f );
3186template <
class derivedT>
3189 if( derivedT::c_stdCamera_tempControl )
3191#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3197 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3199 if( derived().indiTargetUpdate( m_indiP_temp,
target,
ipRecv,
true ) < 0 )
3201 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3207 mx::meta::trueFalseT<derivedT::c_stdCamera_tempControl> tf;
3208 return setTempSetPt( tf );
3216template <
class derivedT>
3219 static_cast<void>( t );
3220 return derived().setTempControl();
3223template <
class derivedT>
3226 static_cast<void>( f );
3230template <
class derivedT>
3233 if( derivedT::c_stdCamera_tempControl )
3235#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3239 if( !
ipRecv.find(
"toggle" ) )
3242 m_tempControlStatusSet =
false;
3244 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3246 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3248 m_tempControlStatusSet =
true;
3249 derived().updateSwitchIfChanged( m_indiP_tempcont,
"toggle", pcf::IndiElement::On,
INDI_BUSY );
3251 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
3253 m_tempControlStatusSet =
false;
3254 derived().updateSwitchIfChanged( m_indiP_tempcont,
"toggle", pcf::IndiElement::Off,
INDI_BUSY );
3257 mx::meta::trueFalseT<derivedT::c_stdCamera_tempControl> tf;
3258 return setTempControl( tf );
3266template <
class derivedT>
3269 static_cast<void>( t );
3270 return derived().setReadoutSpeed();
3273template <
class derivedT>
3276 static_cast<void>( f );
3280template <
class derivedT>
3283 if( derivedT::c_stdCamera_readoutSpeed )
3285#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3289 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3291 std::string newspeed;
3293 for(
size_t i = 0; i < m_readoutSpeedNames.size(); ++i )
3295 if( !
ipRecv.find( m_readoutSpeedNames[i] ) )
3298 if(
ipRecv[m_readoutSpeedNames[i]].getSwitchState() == pcf::IndiElement::On )
3300 if( newspeed !=
"" )
3302 derivedT::template log<text_log>(
"More than one readout speed selected",
logPrio::LOG_ERROR );
3306 newspeed = m_readoutSpeedNames[i];
3310 if( newspeed ==
"" )
3313 m_readoutSpeedNameSet = m_readoutSpeedName;
3317 m_readoutSpeedNameSet = newspeed;
3320 mx::meta::trueFalseT<derivedT::c_stdCamera_readoutSpeed> tf;
3321 return setReadoutSpeed( tf );
3327template <
class derivedT>
3330 static_cast<void>( t );
3331 return derived().setVShiftSpeed();
3334template <
class derivedT>
3337 static_cast<void>( f );
3341template <
class derivedT>
3344 if( derivedT::c_stdCamera_vShiftSpeed )
3346#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3350 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3352 std::string newspeed;
3354 for(
size_t i = 0; i < m_vShiftSpeedNames.size(); ++i )
3356 if( !
ipRecv.find( m_vShiftSpeedNames[i] ) )
3359 if(
ipRecv[m_vShiftSpeedNames[i]].getSwitchState() == pcf::IndiElement::On )
3361 if( newspeed !=
"" )
3363 derivedT::template log<text_log>(
"More than one vShift speed selected",
logPrio::LOG_ERROR );
3367 newspeed = m_vShiftSpeedNames[i];
3371 if( newspeed ==
"" )
3374 m_vShiftSpeedNameSet = m_vShiftSpeedName;
3378 m_vShiftSpeedNameSet = newspeed;
3381 mx::meta::trueFalseT<derivedT::c_stdCamera_vShiftSpeed> tf;
3382 return setVShiftSpeed( tf );
3388template <
class derivedT>
3391 static_cast<void>( t );
3392 return derived().setEMGain();
3395template <
class derivedT>
3398 static_cast<void>( f );
3402template <
class derivedT>
3405 if( derivedT::c_stdCamera_emGain )
3407#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3413 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3415 if( derived().indiTargetUpdate( m_indiP_emGain,
target,
ipRecv,
true ) < 0 )
3417 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3423 mx::meta::trueFalseT<derivedT::c_stdCamera_emGain> tf;
3424 return setEMGain( tf );
3430template <
class derivedT>
3433 static_cast<void>( t );
3434 return derived().setExpTime();
3437template <
class derivedT>
3440 static_cast<void>( f );
3444template <
class derivedT>
3447 if( derivedT::c_stdCamera_exptimeCtrl )
3449#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3455 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3457 if( derived().indiTargetUpdate( m_indiP_exptime,
target,
ipRecv,
true ) < 0 )
3459 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3465 mx::meta::trueFalseT<derivedT::c_stdCamera_exptimeCtrl> tf;
3466 return setExpTime( tf );
3472template <
class derivedT>
3475 static_cast<void>( t );
3476 return derived().setFPS();
3479template <
class derivedT>
3482 static_cast<void>( f );
3486template <
class derivedT>
3489 if( derivedT::c_stdCamera_fpsCtrl )
3491#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3497 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3499 if( derived().indiTargetUpdate( m_indiP_fps,
target,
ipRecv,
true ) < 0 )
3501 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3507 mx::meta::trueFalseT<derivedT::c_stdCamera_fpsCtrl> tf;
3508 return setFPS( tf );
3514template <
class derivedT>
3517 static_cast<void>( t );
3518 return derived().setFanSpeed();
3521template <
class derivedT>
3524 static_cast<void>( f );
3528template <
class derivedT>
3533#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3537 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3539 std::string newFanSpeed;
3541 for(
size_t i = 0; i < m_fanSpeedNames.size(); ++i )
3543 if( !
ipRecv.find( m_fanSpeedNames[i] ) )
3548 if(
ipRecv[m_fanSpeedNames[i]].getSwitchState() == pcf::IndiElement::On )
3550 if( newFanSpeed !=
"" )
3552 derivedT::template log<text_log>(
"More than one fan speed selected",
logPrio::LOG_ERROR );
3556 newFanSpeed = m_fanSpeedNames[i];
3560 if( newFanSpeed ==
"" )
3562 m_fanSpeedNameSet = m_fanSpeedName;
3566 m_fanSpeedNameSet = newFanSpeed;
3569 mx::meta::trueFalseT<c_hasFanSpeed> tf;
3570 return setFanSpeed( tf );
3576template <
class derivedT>
3579 static_cast<void>( t );
3580 return derived().setAnalogGain();
3583template <
class derivedT>
3586 static_cast<void>( f );
3590template <
class derivedT>
3593 if( c_hasAnalogGain )
3595#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3599 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3601 std::string newAnalogGain;
3603 for(
size_t i = 0; i < m_analogGainNames.size(); ++i )
3605 if( !
ipRecv.find( m_analogGainNames[i] ) )
3610 if(
ipRecv[m_analogGainNames[i]].getSwitchState() == pcf::IndiElement::On )
3612 if( newAnalogGain !=
"" )
3614 derivedT::template log<text_log>(
"More than one analog gain selected",
logPrio::LOG_ERROR );
3618 newAnalogGain = m_analogGainNames[i];
3622 if( newAnalogGain ==
"" )
3624 m_analogGainNameSet = m_analogGainName;
3628 m_analogGainNameSet = newAnalogGain;
3631 mx::meta::trueFalseT<c_hasAnalogGain> tf;
3632 return setAnalogGain( tf );
3638template <
class derivedT>
3641 static_cast<void>( t );
3642 return derived().setLED();
3645template <
class derivedT>
3648 static_cast<void>( f );
3652template <
class derivedT>
3657#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3661 if( !
ipRecv.find(
"toggle" ) )
3666 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
3668 m_ledStateSet =
false;
3671 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3673 m_ledStateSet =
true;
3676 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3678 mx::meta::trueFalseT<c_hasLED> tf;
3679 return setLED( tf );
3685template <
class derivedT>
3688 static_cast<void>( t );
3689 return derived().setSynchro();
3692template <
class derivedT>
3695 static_cast<void>( f );
3699template <
class derivedT>
3702 if( derivedT::c_stdCamera_synchro )
3704#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3708 if( !
ipRecv.find(
"toggle" ) )
3711 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
3713 m_synchroSet =
false;
3716 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3718 m_synchroSet =
true;
3721 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3723 mx::meta::trueFalseT<derivedT::c_stdCamera_synchro> tf;
3724 return setSynchro( tf );
3730template <
class derivedT>
3733 if( derivedT::c_stdCamera_usesModes )
3735#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3739 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3741 if(
ipRecv.getName() != m_indiP_mode.getName() )
3743 derivedT::template log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
3748 std::string newName =
"";
3749 for(
auto it = m_cameraModes.begin();
it != m_cameraModes.end(); ++
it )
3754 if(
ipRecv[
it->first].getSwitchState() == pcf::IndiElement::On )
3758 derivedT::template log<text_log>(
"More than one camera mode selected",
logPrio::LOG_ERROR );
3762 newName =
it->first;
3772 m_nextMode = newName;
3773 derived().m_reconfig =
true;
3783template <
class derivedT>
3786#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3790 if( !
ipRecv.find(
"request" ) )
3793 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
3795 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3798 m_indiP_reconfig,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
3800 m_nextMode = m_modeName;
3801 derived().m_reconfig =
true;
3808template <
class derivedT>
3811 static_cast<void>( t );
3812 return derived().setCropMode();
3815template <
class derivedT>
3818 static_cast<void>( f );
3822template <
class derivedT>
3825 if( derivedT::c_stdCamera_cropMode )
3827#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3831 if( !
ipRecv.find(
"toggle" ) )
3834 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
3836 m_cropModeSet =
false;
3839 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
3841 m_cropModeSet =
true;
3844 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3846 mx::meta::trueFalseT<derivedT::c_stdCamera_cropMode> tf;
3847 return setCropMode( tf );
3854template <
class derivedT>
3857#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3863 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3865 if( derived().indiTargetUpdate( m_indiP_roi_x,
target,
ipRecv,
false ) < 0 )
3867 m_nextROI.x = m_currentROI.x;
3868 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3877template <
class derivedT>
3880#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3886 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3888 if( derived().indiTargetUpdate( m_indiP_roi_y,
target,
ipRecv,
false ) < 0 )
3890 m_nextROI.y = m_currentROI.y;
3891 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3900template <
class derivedT>
3903#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3909 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3911 if( derived().indiTargetUpdate( m_indiP_roi_w,
target,
ipRecv,
false ) < 0 )
3913 m_nextROI.w = m_currentROI.w;
3914 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3923template <
class derivedT>
3926#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3932 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3934 if( derived().indiTargetUpdate( m_indiP_roi_h,
target,
ipRecv,
false ) < 0 )
3936 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3937 m_nextROI.h = m_currentROI.h;
3946template <
class derivedT>
3949#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3955 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3957 if( derived().indiTargetUpdate( m_indiP_roi_bin_x,
target,
ipRecv,
false ) < 0 )
3959 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3960 m_nextROI.bin_x = m_currentROI.bin_x;
3964 m_nextROI.bin_x =
target;
3969template <
class derivedT>
3972#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
3978 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
3980 if( derived().indiTargetUpdate( m_indiP_roi_bin_y,
target,
ipRecv,
false ) < 0 )
3982 derivedT::template log<software_error>( { __FILE__, __LINE__ } );
3983 m_nextROI.bin_y = m_currentROI.bin_y;
3987 m_nextROI.bin_y =
target;
3992template <
class derivedT>
3995 static_cast<void>( t );
3996 return derived().checkNextROI();
3999template <
class derivedT>
4002 static_cast<void>( f );
4006template <
class derivedT>
4009 if( derivedT::c_stdCamera_usesROI )
4011#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4015 if( !
ipRecv.find(
"request" ) )
4018 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4020 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4023 m_indiP_roi_check,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4025 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4026 return checkNextROI( tf );
4035template <
class derivedT>
4038 static_cast<void>( t );
4039 return derived().setNextROI();
4042template <
class derivedT>
4045 static_cast<void>( f );
4049template <
class derivedT>
4052 if( derivedT::c_stdCamera_usesROI )
4054#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4058 if( !
ipRecv.find(
"request" ) )
4061 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4063 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4066 m_indiP_roi_set,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4068 m_lastROI = m_currentROI;
4070 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4071 return setNextROI( tf );
4080template <
class derivedT>
4083 if( derivedT::c_stdCamera_usesROI )
4085#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4089 if( !
ipRecv.find(
"request" ) )
4092 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4094 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4097 m_indiP_roi_full,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4099 m_nextROI.x = m_full_x;
4100 m_nextROI.y = m_full_y;
4101 m_nextROI.w = m_full_w;
4102 m_nextROI.h = m_full_h;
4103 m_nextROI.bin_x = m_full_bin_x;
4104 m_nextROI.bin_y = m_full_bin_y;
4105 m_lastROI = m_currentROI;
4106 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4107 return setNextROI( tf );
4116template <
class derivedT>
4119 if( derivedT::c_stdCamera_usesROI )
4121#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4125 if( !
ipRecv.find(
"request" ) )
4128 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4130 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4133 m_indiP_roi_fullbin,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4137 if( m_full_currbin_x == 0 )
4139 derivedT::template log<text_log>(
"current-binning full ROI not implemented for this camera",
4141 m_full_currbin_x = m_full_x;
4142 m_full_currbin_y = m_full_y;
4143 m_full_currbin_w = m_full_w;
4144 m_full_currbin_h = m_full_h;
4148 m_nextROI.x = m_full_currbin_x;
4149 m_nextROI.y = m_full_currbin_y;
4150 m_nextROI.w = m_full_currbin_w;
4151 m_nextROI.h = m_full_currbin_h;
4155 m_nextROI.bin_x = m_full_bin_x;
4156 m_nextROI.bin_y = m_full_bin_y;
4159 m_full_currbin_x = 0;
4160 m_full_currbin_y = 0;
4161 m_full_currbin_w = 0;
4162 m_full_currbin_h = 0;
4166 m_nextROI.bin_x = m_currentROI.bin_x;
4167 m_nextROI.bin_y = m_currentROI.bin_y;
4170 m_lastROI = m_currentROI;
4171 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4172 return setNextROI( tf );
4181template <
class derivedT>
4184 if( derivedT::c_stdCamera_usesROI )
4186#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4190 if( !
ipRecv.find(
"request" ) )
4193 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4195 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4198 m_indiP_roi_loadlast,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4200 m_nextROI = m_lastROI;
4210template <
class derivedT>
4213 if( derivedT::c_stdCamera_usesROI )
4215#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4218 if( !
ipRecv.find(
"request" ) )
4221 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4223 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4226 m_indiP_roi_last,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4228 m_nextROI = m_lastROI;
4229 m_lastROI = m_currentROI;
4230 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4231 return setNextROI( tf );
4240template <
class derivedT>
4243 if( derivedT::c_stdCamera_usesROI )
4245#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4249 if( !
ipRecv.find(
"request" ) )
4252 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4254 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4257 m_indiP_roi_default,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4259 m_nextROI.x = m_default_x;
4260 m_nextROI.y = m_default_y;
4261 m_nextROI.w = m_default_w;
4262 m_nextROI.h = m_default_h;
4263 m_nextROI.bin_x = m_default_bin_x;
4264 m_nextROI.bin_y = m_default_bin_y;
4265 m_lastROI = m_currentROI;
4266 mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
4267 return setNextROI( tf );
4276template <
class derivedT>
4279 static_cast<void>( t );
4280 return derived().setShutter( ss );
4283template <
class derivedT>
4286 static_cast<void>( ss );
4287 static_cast<void>( f );
4291template <
class derivedT>
4294 if( derivedT::c_stdCamera_hasShutter )
4296#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4300 if( !
ipRecv.find(
"toggle" ) )
4303 mx::meta::trueFalseT<derivedT::c_stdCamera_hasShutter> tf;
4305 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
4307 setShutter( 1, tf );
4310 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
4312 setShutter( 0, tf );
4320template <
class derivedT>
4323 static_cast<void>( t );
4324 return derived().checkFocus();
4327template <
class derivedT>
4330 static_cast<void>( f );
4334template <
class derivedT>
4337 static_cast<void>( t );
4338 return derived().gotoFocus();
4341template <
class derivedT>
4344 static_cast<void>( f );
4348template <
class derivedT>
4351 if( c_hasFocus && m_hasFocus )
4353#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
4357 if( !
ipRecv.find(
"request" ) )
4362 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On )
4364 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4367 m_indiP_gotoFocus,
"request", pcf::IndiElement::Off, derived().m_indiDriver,
INDI_IDLE );
4369 mx::meta::trueFalseT<c_hasFocus> tf;
4370 return gotoFocus( tf );
4377template <
class derivedT>
4380 return static_cast<derivedT *
>( app )->setCallBack_focusMonitored(
ipRecv );
4383template <
class derivedT>
4386 for(
size_t n = 0; n < m_indiP_focusMonitoredProperties.size(); ++n )
4388 if(
ipRecv.getDevice() == m_indiP_focusMonitoredProperties[n].getDevice() &&
4389 ipRecv.getName() == m_indiP_focusMonitoredProperties[n].getName() )
4391 m_indiP_focusMonitoredProperties[n] =
ipRecv;
4393 if( c_hasFocus && m_hasFocus &&
static_cast<int>( n ) == m_focusStateSourceIndex )
4395 std::unique_lock<std::mutex>
lock( derived().m_indiMutex );
4396 updateFocusStateProperty();
4406template <
class derivedT>
4409 static_cast<void>( t );
4410 return derived().stateString();
4413template <
class derivedT>
4416 static_cast<void>( f );
4420template <
class derivedT>
4423 static_cast<void>( t );
4424 return derived().stateStringValid();
4427template <
class derivedT>
4430 static_cast<void>( f );
4434template <
class derivedT>
4439 if( !derived().m_indiDriver )
4442 if( derivedT::c_stdCamera_readoutSpeed )
4445 m_indiP_readoutSpeed, m_readoutSpeedName, derived().m_indiDriver,
INDI_OK );
4448 if( derivedT::c_stdCamera_vShiftSpeed )
4451 m_indiP_vShiftSpeed, m_vShiftSpeedName, derived().m_indiDriver,
INDI_OK );
4454 if( derivedT::c_stdCamera_emGain )
4456 derived().updateIfChanged( m_indiP_emGain,
"current", m_emGain,
INDI_IDLE );
4457 derived().updateIfChanged( m_indiP_emGain,
"target", m_emGainSet,
INDI_IDLE );
4460 if( derivedT::c_stdCamera_exptimeCtrl )
4462 derived().updateIfChanged( m_indiP_exptime,
"current", m_expTime,
INDI_IDLE );
4463 derived().updateIfChanged( m_indiP_exptime,
"target", m_expTimeSet,
INDI_IDLE );
4466 if( derivedT::c_stdCamera_fpsCtrl )
4468 derived().updateIfChanged( m_indiP_fps,
"current", m_fps,
INDI_IDLE );
4469 derived().updateIfChanged( m_indiP_fps,
"target", m_fpsSet,
INDI_IDLE );
4471 else if( derivedT::c_stdCamera_fps )
4473 derived().updateIfChanged( m_indiP_fps,
"current", m_fps,
INDI_IDLE );
4476 if( c_hasFanSpeed && m_fanSpeedControlEnabled && m_fanSpeedValid )
4481 if( c_hasLED && m_ledStateValid )
4485 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::On,
INDI_OK );
4489 derived().updateSwitchIfChanged( m_indiP_led,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
4493 if( derivedT::c_stdCamera_synchro )
4495 if( m_synchro ==
false )
4497 derived().updateSwitchIfChanged( m_indiP_synchro,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
4501 derived().updateSwitchIfChanged( m_indiP_synchro,
"toggle", pcf::IndiElement::On,
INDI_OK );
4505 if( derivedT::c_stdCamera_usesModes )
4507 auto st = pcf::IndiProperty::Ok;
4508 if( m_nextMode !=
"" )
4509 st = pcf::IndiProperty::Busy;
4511 for(
auto it = m_cameraModes.begin();
it != m_cameraModes.end(); ++
it )
4513 if(
it->first == m_modeName )
4514 derived().updateSwitchIfChanged( m_indiP_mode,
it->first, pcf::IndiElement::On, st );
4516 derived().updateSwitchIfChanged( m_indiP_mode,
it->first, pcf::IndiElement::Off, st );
4520 if( derivedT::c_stdCamera_cropMode )
4522 if( m_cropMode ==
false )
4524 derived().updateSwitchIfChanged( m_indiP_cropMode,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
4528 derived().updateSwitchIfChanged( m_indiP_cropMode,
"toggle", pcf::IndiElement::On,
INDI_OK );
4532 if( derivedT::c_stdCamera_usesROI )
4536 derived().updateIfChanged( m_indiP_fullROI,
"x", m_full_x,
INDI_IDLE );
4537 derived().updateIfChanged( m_indiP_fullROI,
"y", m_full_y,
INDI_IDLE );
4538 derived().updateIfChanged( m_indiP_fullROI,
"w", m_full_w,
INDI_IDLE );
4539 derived().updateIfChanged( m_indiP_fullROI,
"h", m_full_h,
INDI_IDLE );
4542 if( derivedT::c_stdCamera_tempControl )
4544 if( m_tempControlStatus ==
false )
4546 derived().updateSwitchIfChanged( m_indiP_tempcont,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
4547 derived().updateIfChanged( m_indiP_temp,
"current", m_ccdTemp,
INDI_IDLE );
4548 derived().updateIfChanged( m_indiP_temp,
"target", m_ccdTempSetpt,
INDI_IDLE );
4549 derived().updateIfChanged( m_indiP_tempstat,
"status", m_tempControlStatusStr,
INDI_IDLE );
4553 if( m_tempControlOnTarget )
4555 derived().updateSwitchIfChanged( m_indiP_tempcont,
"toggle", pcf::IndiElement::On,
INDI_OK );
4556 derived().updateIfChanged( m_indiP_temp,
"current", m_ccdTemp,
INDI_OK );
4557 derived().updateIfChanged( m_indiP_temp,
"target", m_ccdTempSetpt,
INDI_OK );
4558 derived().updateIfChanged( m_indiP_tempstat,
"status", m_tempControlStatusStr,
INDI_OK );
4562 derived().updateSwitchIfChanged( m_indiP_tempcont,
"toggle", pcf::IndiElement::On,
INDI_BUSY );
4563 derived().updateIfChanged( m_indiP_temp,
"current", m_ccdTemp,
INDI_BUSY );
4564 derived().updateIfChanged( m_indiP_temp,
"target", m_ccdTempSetpt,
INDI_BUSY );
4565 derived().updateIfChanged( m_indiP_tempstat,
"status", m_tempControlStatusStr,
INDI_BUSY );
4569 else if( derivedT::c_stdCamera_temp )
4571 derived().updateIfChanged( m_indiP_temp,
"current", m_ccdTemp,
INDI_IDLE );
4574 if( derivedT::c_stdCamera_hasShutter )
4576 if( m_shutterStatus ==
"OPERATING" )
4578 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_BUSY );
4580 if( m_shutterStatus ==
"POWERON" || m_shutterStatus ==
"READY" )
4582 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_IDLE );
4586 derived().updateIfChanged( m_indiP_shutterStatus,
"status", m_shutterStatus,
INDI_IDLE );
4589 if( m_shutterState == 0 )
4591 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::On,
INDI_OK );
4595 derived().updateSwitchIfChanged( m_indiP_shutter,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
4599 if( c_hasFocus && m_hasFocus )
4601 updateFocusStateProperty();
4602 derived().updateSwitchIfChanged( m_indiP_gotoFocus,
"request", pcf::IndiElement::Off,
INDI_IDLE );
4605 if( derivedT::c_stdCamera_usesStateString )
4607 mx::meta::trueFalseT<derivedT::c_stdCamera_usesStateString> tf;
4608 derived().updateIfChanged( m_indiP_stateString,
"current", stateString( tf ),
INDI_IDLE );
4609 if( stateStringValid( tf ) )
4611 derived().updateIfChanged( m_indiP_stateString,
"valid",
"yes",
INDI_IDLE );
4615 derived().updateIfChanged( m_indiP_stateString,
"valid",
"no",
INDI_IDLE );
4620 catch(
const std::exception &e )
4623 { __FILE__, __LINE__, std::string(
"Exception caught: " ) + e.what() } );
4627template <
class derivedT>
4630 static std::string last_mode;
4631 static roi last_roi;
4632 static float last_expTime = -1e30;
4633 static float last_fps = 0;
4634 static float last_adcSpeed = -1;
4635 static float last_emGain = -1;
4636 static float last_ccdTemp = 0;
4637 static float last_ccdTempSetpt = 0;
4638 static bool last_tempControlStatus = 0;
4639 static bool last_tempControlOnTarget = 0;
4640 static std::string last_tempControlStatusStr;
4641 static std::string last_shutterStatus;
4642 static int last_shutterState =
false;
4643 static bool last_synchro =
false;
4644 static float last_vshiftSpeed = -1;
4645 static bool last_cropMode =
false;
4646 static std::string last_fanSpeed;
4647 static std::string last_analogGain;
4648 static bool last_ledState =
false;
4649 static std::string last_readoutSpeed;
4651 if( force || m_modeName != last_mode || m_currentROI.x != last_roi.
x || m_currentROI.y != last_roi.
y ||
4652 m_currentROI.w != last_roi.
w || m_currentROI.h != last_roi.
h || m_currentROI.bin_x != last_roi.
bin_x ||
4653 m_currentROI.bin_y != last_roi.
bin_y || m_expTime != last_expTime || m_fps != last_fps ||
4654 m_emGain != last_emGain || m_adcSpeed != last_adcSpeed || m_ccdTemp != last_ccdTemp ||
4655 m_ccdTempSetpt != last_ccdTempSetpt || m_tempControlStatus != last_tempControlStatus ||
4656 m_tempControlOnTarget != last_tempControlOnTarget || m_tempControlStatusStr != last_tempControlStatusStr ||
4657 m_shutterStatus != last_shutterStatus || m_shutterState != last_shutterState || m_synchro != last_synchro ||
4658 m_vshiftSpeed != last_vshiftSpeed || m_cropMode != last_cropMode || m_readoutSpeedName != last_readoutSpeed ||
4659 ( c_hasFanSpeed && m_fanSpeedValid && m_fanSpeedName != last_fanSpeed ) ||
4660 ( c_hasAnalogGain && m_analogGainValid && m_analogGainName != last_analogGain ) ||
4661 ( c_hasLED && m_ledStateValid && m_ledState != last_ledState ) )
4663 derived().template telem<telem_stdcam>(
4677 (uint8_t)m_tempControlStatus,
4678 (uint8_t)m_tempControlOnTarget,
4679 m_tempControlStatusStr,
4681 (int8_t)m_shutterState,
4684 (uint8_t)m_cropMode,
4685 c_hasFanSpeed && m_fanSpeedValid ? m_fanSpeedName : std::string(
"" ),
4687 c_hasAnalogGain && m_analogGainValid ? m_analogGainName : std::string(
"" ),
4688 c_hasLED && m_ledStateValid ?
static_cast<int8_t
>( m_ledState ? 1 : 0 ) :
static_cast<int8_t
>( -1 ) } );
4690 last_mode = m_modeName;
4691 last_roi = m_currentROI;
4692 last_expTime = m_expTime;
4694 last_emGain = m_emGain;
4695 last_adcSpeed = m_adcSpeed;
4696 last_ccdTemp = m_ccdTemp;
4697 last_ccdTempSetpt = m_ccdTempSetpt;
4698 last_tempControlStatus = m_tempControlStatus;
4699 last_tempControlOnTarget = m_tempControlOnTarget;
4700 last_tempControlStatusStr = m_tempControlStatusStr;
4701 last_shutterStatus = m_shutterStatus;
4702 last_shutterState = m_shutterState;
4703 last_synchro = m_synchro;
4704 last_vshiftSpeed = m_vshiftSpeed;
4705 last_cropMode = m_cropMode;
4706 last_fanSpeed = c_hasFanSpeed && m_fanSpeedValid ? m_fanSpeedName : std::string(
"" );
4707 last_analogGain = c_hasAnalogGain && m_analogGainValid ? m_analogGainName : std::string(
"" );
4708 last_ledState = m_ledState;
4709 last_readoutSpeed = m_readoutSpeedName;
4719#define STDCAMERA_SETUP_CONFIG( cfig ) \
4720 if( stdCameraT::setupConfig( cfig ) < 0 ) \
4722 log<software_error>( { __FILE__, __LINE__, "Error from stdCameraT::setupConfig" } ); \
4723 m_shutdown = true; \
4731#define STDCAMERA_LOAD_CONFIG( cfig ) \
4732 if( stdCameraT::loadConfig( cfig ) < 0 ) \
4734 return log<software_error, -1>( { __FILE__, __LINE__, "Error from stdCameraT::loadConfig" } ); \
4738#define STDCAMERA_APP_STARTUP \
4739 if( stdCameraT::appStartup() < 0 ) \
4741 return log<software_error, -1>( { __FILE__, __LINE__, "Error from stdCameraT::appStartup" } ); \
4745#define STDCAMERA_APP_LOGIC \
4746 if( stdCameraT::appLogic() < 0 ) \
4748 return log<software_error, -1>( { __FILE__, __LINE__, "Error from stdCameraT::appLogic" } ); \
4752#define STDCAMERA_UPDATE_INDI \
4753 if( stdCameraT::updateINDI() < 0 ) \
4755 return log<software_error, -1>( { __FILE__, __LINE__, "Error from stdCameraT::updateINDI" } ); \
4759#define STDCAMERA_APP_SHUTDOWN \
4760 if( stdCameraT::appShutdown() < 0 ) \
4762 return log<software_error, -1>( { __FILE__, __LINE__, "Error from stdCameraT::appShutdown" } ); \
MagAO-X standard camera interface.
float m_maxEMGain
The configurable maximum EM gain. To be enforced in derivedT.
std::vector< std::string > m_readoutSpeedNames
float m_minExpTime
The minimum exposure time, used for INDI attributes.
pcf::IndiProperty m_indiP_roi_fullbin
Property used to trigger setting the full in current binning ROI.
float m_fpsSet
The commanded fps, as set by user.
int newCallBack_temp(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp request.
int newCallBack_cropMode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW cropMode request.
static constexpr bool c_hasLED
True when the derived camera exposes LED control.
bool m_synchroSet
Target status of m_synchro.
pcf::IndiProperty m_indiP_roi_y
Property used to set the ROI x center coordinate.
int createFanSpeed(const mx::meta::trueFalseT< true > &t)
int createReadoutSpeed(const mx::meta::trueFalseT< true > &t)
int m_full_currbin_w
The current-binning full ROI width.
int setShutter(int ss, const mx::meta::trueFalseT< true > &t)
Interface to setShutter when the derivedT has a shutter.
std::vector< std::string > m_analogGainNames
Valid analog-gain option names for the INDI selection switch.
float m_default_x
Power-on ROI center x coordinate.
std::string m_tempControlStatusStr
Camera specific description of temperature control status.
float m_emGain
The camera's current EM gain (if available).
int m_full_bin_x
The x-binning in the full ROI.
int newCallBack_readoutSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW readout speed request.
std::vector< std::string > m_fanSpeedNames
Valid fan-control option names for the INDI selection switch.
std::vector< std::string > m_readoutSpeedNameLabels
std::string m_analogGainNameSet
Requested analog-gain option name.
float m_full_currbin_x
The current-binning full ROI center x coordinate.
int m_full_w
The full ROI width.
float m_emGainSet
The camera's EM gain, as set by the user.
std::string m_vShiftSpeedNameSet
The user requested vshift speed name, to be set by derived()
int newCallBack_led(const pcf::IndiProperty &ipRecv)
Callback to process a NEW LED request.
bool m_cropModeSet
Desired status of crop mode ROIs, if enabled for this camera.
pcf::IndiProperty m_indiP_led
Property used to control the status LED state.
int newCallBack_roi_bin_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_y request.
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
pcf::IndiProperty m_indiP_shutterStatus
State of the shutter. 0 = shut, 1 = open, -1 = unknown.
std::vector< std::string > m_focusMonitoredPropertyKeys
Unique INDI keys monitored for the focus-state and goto-focus helpers.
float m_expTime
The current exposure time, in seconds.
int setExpTime(const mx::meta::trueFalseT< true > &t)
Interface to setExpTime when the derivedT uses exposure time controls.
int m_focusStateSourceIndex
Index of m_focusStateSource within m_indiP_focusMonitoredProperties, or -1 when unused.
std::string m_nextMode
The mode to be set by the next reconfiguration.
int setFanSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setFanSpeed when the derivedT exposes fan controls.
pcf::IndiProperty m_indiP_tempstat
int m_default_bin_x
Power-on ROI x binning.
int m_default_w
Power-on ROI width.
int setTempControl(const mx::meta::trueFalseT< true > &t)
Interface to setTempControl when the derivedT has temperature control.
int newCallBack_roi_h(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_h request.
bool m_ledStateSet
Requested status LED state.
std::vector< pcf::IndiProperty > m_indiP_focusMonitoredProperties
Cached external switch properties monitored for the focus helpers.
int recordCamera(bool force=false)
bool m_cropMode
Status of crop mode ROIs, if enabled for this camera.
float m_maxExpTime
The maximum exposure time, used for INDI attributes.
float m_stepFPS
The FPS step size, used for INDI attributes.
int newCallBack_mode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW mode request.
static constexpr bool c_hasFanSpeed
True when the derived camera exposes fan-speed control.
int setAnalogGain(const mx::meta::trueFalseT< true > &t)
Interface to setAnalogGain when the derivedT exposes analog-gain controls.
int m_default_h
Power-on ROI height.
pcf::IndiProperty m_indiP_roi_last
Property used to trigger setting the last ROI.
pcf::IndiProperty m_indiP_temp
static constexpr bool c_hasFocus
float m_expTimeSet
The exposure time, in seconds, as set by user.
void updateFocusStateProperty()
Refresh the published focus.state property from the current helper or derived focus implementation.
pcf::IndiProperty m_indiP_roi_h
Property used to set the ROI height.
std::string m_fanSpeedNameSet
Requested fan-control option name.
std::string m_focusStateSource
INDI key (device.property) of the switch property used by checkFocusSwitchState.
int m_full_h
The full ROI height.
bool m_ledStateValid
True once the current LED state is known.
pcf::IndiProperty m_indiP_synchro
bool m_fanSpeedControlEnabled
Whether or not fan-speed control is published through INDI.
std::string m_analogGainName
Current analog-gain option name.
int m_full_bin_y
The y-binning in the full ROI.
int checkNextROI(const mx::meta::trueFalseT< true > &t)
Interface to checkNextROI when the derivedT uses ROIs.
int gotoFocus(const mx::meta::trueFalseT< true > &t)
Interface to gotoFocus when the derivedT exposes focus support.
int setVShiftSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setVShiftSpeed when the derivedT has vshift speed control.
float m_full_y
The full ROI center y coordinate.
int setLED(const mx::meta::trueFalseT< true > &t)
Interface to setLED when the derivedT exposes LED controls.
static int st_newCallBack_stdCamera(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for stdCamera properties.
float m_maxFPS
The maximum FPS, used for INDI attributes.
std::string m_readoutSpeedName
The current readout speed name.
bool checkFocusSwitchState()
Evaluate the configured focus-state switch helper as an in-focus boolean.
float m_ccdTempSetpt
The desired temperature, in C.
bool m_tempControlStatus
Whether or not temperature control is active.
pcf::IndiProperty m_indiP_fps
int newCallBack_roi_last(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_last request.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
bool m_defaultLEDState
The default LED state to apply after power on.
std::string m_focusGotoTargetDevice
Device portion parsed from m_focusGotoTargetProperty.
std::string m_focusGotoTargetProperty
INDI key (device.property) of the switch property commanded by gotoFocus().
pcf::IndiProperty m_indiP_roi_loadlast
Property used to trigger loading the last ROI as the target.
std::vector< std::string > m_focusGotoSourceProperties
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
int newCallBack_roi_set(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_set request.
int newCallBack_analogGain(const pcf::IndiProperty &ipRecv)
Callback to process a NEW analog-gain request.
pcf::IndiProperty m_indiP_roi_default
Property used to trigger setting the default and startup ROI.
int newCallBack_stdCamera(const pcf::IndiProperty &ipRecv)
The callback function for stdCamera properties.
std::string m_focusGotoTargetName
Property-name portion parsed from m_focusGotoTargetProperty.
pcf::IndiProperty m_indiP_focus
Read-only switch property reporting whether the current state is in focus.
std::string m_modeName
The current mode name.
pcf::IndiProperty m_indiP_reconfig
Request switch which forces the framegrabber to go through the reconfigure process.
int setSynchro(const mx::meta::trueFalseT< true > &t)
Interface to setSynchro when the derivedT has synchronization.
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
int newCallBack_roi_loadlast(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_loadlast request.
pcf::IndiProperty m_indiP_readoutSpeed
pcf::IndiProperty m_indiP_gotoFocus
Request switch property used to command the current focus target.
int setEMGain(const mx::meta::trueFalseT< true > &t)
Interface to setEMGain when the derivedT has EM Gain.
bool m_hasFocus
Runtime flag enabling focus-state reporting and goto-focus control publication.
int newCallBack_vShiftSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW vshift speed request.
std::string m_startupMode
The camera mode to load during first init after a power-on.
pcf::IndiProperty m_indiP_roi_check
Property used to trigger checking the target ROI.
std::string m_focusStateElement
bool m_focusGotoHelperConfigured
True when stdCamera should derive goto-focus commands from external switch properties.
pcf::IndiProperty m_indiP_vShiftSpeed
int newCallBack_roi_check(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_check request.
pcf::IndiProperty m_indiP_fanSpeed
Property used to select the fan-speed mode.
std::string m_fanSpeedName
Current fan-control option name.
int newCallBack_roi_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_x request.
float m_full_x
The full ROI center x coordinate.
bool checkFocus(const mx::meta::trueFalseT< true > &t)
Interface to checkFocus when the derivedT exposes focus support.
float m_startupTemp
The temperature to set after a power-on. Set to <= -999 to not use [default].
int appLogic()
Application logic.
int m_full_currbin_h
The current-binning full ROI height.
std::vector< int > m_focusGotoSourceIndices
Indices of m_focusGotoSourceProperties within m_indiP_focusMonitoredProperties.
static constexpr bool c_hasAnalogGain
True when the derived camera exposes analog-gain control.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_shutterStatus
pcf::IndiProperty m_indiP_exptime
int newCallBack_shutter(const pcf::IndiProperty &ipRecv)
Callback to process a NEW shutter request.
bool m_synchro
Status of synchronization, true is on, false is off.
std::string m_vShiftSpeedName
The current vshift speed name.
int newCallBack_roi_full(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_full request.
int setCropMode(const mx::meta::trueFalseT< true > &t)
Interface to setCropMode when the derivedT has crop mode.
std::string m_defaultFanSpeed
The default fan speed to apply after power on.
pcf::IndiProperty m_indiP_emGain
float m_ccdTemp
The current temperature, in C.
bool m_fanSpeedValid
True once the current fan-control state is known.
int updateINDI()
Update the INDI properties for this device controller.
std::vector< std::string > m_vShiftSpeedNames
int sendGotoFocusCommand()
Format and send the configured goto-focus switch command.
int newCallBack_fps(const pcf::IndiProperty &ipRecv)
Callback to process a NEW fps request.
std::string m_defaultVShiftSpeed
The default readout speed of the camera.
int newCallBack_roi_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_y request.
int setCallBack_focusMonitored(const pcf::IndiProperty &ipRecv)
The callback which caches external focus-helper switch-property updates.
pcf::IndiProperty m_indiP_tempcont
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
int createVShiftSpeed(const mx::meta::trueFalseT< true > &t)
cameraConfigMap m_cameraModes
Map holding the possible camera mode configurations.
float m_stepExpTime
The maximum exposure time stepsize, used for INDI attributes.
int whilePowerOff()
Actions while powered off.
bool m_focusStateHelperConfigured
True when stdCamera should evaluate focus state from an external switch property.
int setFPS(const mx::meta::trueFalseT< true > &t)
Interface to setFPS when the derivedT uses FPS controls.
int newCallBack_reconfigure(const pcf::IndiProperty &ipRecv)
Callback to process a NEW reconfigure request.
int newCallBack_emgain(const pcf::IndiProperty &ipRecv)
Callback to process a NEW EM gain request.
float m_full_currbin_y
The current-binning full ROI center y coordinate.
int appStartup()
Startup function.
int newCallBack_roi_bin_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_x request.
std::vector< std::string > m_vShiftSpeedNameLabels
int setTempSetPt(const mx::meta::trueFalseT< true > &t)
Interface to setTempSetPt when the derivedT has temperature control.
bool m_analogGainValid
True once the current analog-gain state is known.
pcf::IndiProperty m_indiP_roi_full
Property used to trigger setting the full ROI.
int newCallBack_synchro(const pcf::IndiProperty &ipRecv)
Callback to process a NEW synchro request.
std::string m_focusGotoFormat
Literal {} placeholder format used to build the goto-focus preset name.
std::vector< std::string > m_analogGainNameLabels
Optional GUI labels for the analog-gain options.
int newCallBack_roi_default(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_default request.
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
int appShutdown()
Application shutdown.
pcf::IndiProperty m_indiP_shutter
Property used to control the shutter, a switch.
std::vector< std::string > m_fanSpeedNameLabels
Optional GUI labels for the fan-control options.
int newCallBack_roi_w(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_w request.
bool m_ledState
Current status LED state.
pcf::IndiProperty m_indiP_stateString
pcf::IndiProperty m_indiP_mode
Property used to report the current mode.
int newCallBack_gotoFocus(const pcf::IndiProperty &ipRecv)
Callback to process a NEW goto-focus request.
pcf::IndiProperty m_indiP_cropMode
Property used to toggle crop mode on and off.
float m_default_y
Power-on ROI center y coordinate.
int setNextROI(const mx::meta::trueFalseT< true > &t)
Interface to setNextROI when the derivedT uses ROIs.
pcf::IndiProperty m_indiP_fullROI
Property used to preset the full ROI dimensions.
bool stateStringValid(const mx::meta::trueFalseT< true > &t)
Interface to stateStringValid when the derivedT provides it.
float m_fps
The current FPS.
std::string stateString(const mx::meta::trueFalseT< true > &t)
Interface to stateString when the derivedT provides it.
bool m_focusStateOnMeansInFocus
pcf::IndiProperty m_indiP_roi_bin_y
Property used to set the ROI y binning.
pcf::IndiProperty m_indiP_analogGain
Property used to select the analog-gain mode.
pcf::IndiProperty m_indiP_roi_x
Property used to set the ROI x center coordinate.
int newCallBack_roi_fullbin(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_fullbin request.
int newCallBack_temp_controller(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp control request.
int newCallBack_exptime(const pcf::IndiProperty &ipRecv)
Callback to process a NEW exposure time request.
int newCallBack_fanSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW fan speed request.
int setReadoutSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setReadoutSpeed when the derivedT has readout speed control.
int m_default_bin_y
Power-on ROI y binning.
bool m_tempControlStatusSet
Desired state of temperature control.
float m_minFPS
The minimum FPS, used for INDI attributes.
int onPowerOff()
Actions on power off.
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
static int st_setCallBack_focusMonitored(void *app, const pcf::IndiProperty &ipRecv)
The static callback function registered for external focus-helper switch properties.
~stdCamera() noexcept
Destructor.
std::unordered_map< std::string, cameraConfig > cameraConfigMap
int loadCameraConfig(cameraConfigMap &ccmap, mx::app::appConfigurator &config)
Load the camera configurations contained in the app configuration into a map.
void stripQuotedWhitespace(std::string &value)
Strip leading and trailing whitespace and one matching pair of wrapping double quotes.
std::string m_serialCommand
The command to send to the camera to place it in this mode.
std::string m_configFile
The file to use for this mode, e.g. an EDT configuration file.
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.
void updateSelectionSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the values of a one-of-many INDI switch vector, but only if it has changed.
int parseIndiKey(std::string &devName, std::string &propName, const std::string &key)
Parse an INDI key into the device and property names.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &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
std::unique_lock< std::mutex > lock(m_indiMutex)
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
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 CAMCTRL_E_NOCONFIGS
Detect whether a derived camera exposes stdCamera analog-gain control support.
Detect whether a derived camera exposes stdCamera fan-speed control support.
Detect whether a derived camera exposes stdCamera focus-state and goto-focus support.
Detect whether a derived camera exposes stdCamera LED control support.
@ OPERATING
The device is operating, other than homing.
@ READY
The device is ready for operation, but is not operating.
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
Software CRITICAL log entry.