LCOV - code coverage report
Current view: top level - apps/xInstGraph/xigNodes - stdMotionNode.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 74.2 % 271 201
Test Date: 2026-01-03 21:03:39 Functions: 100.0 % 21 21

            Line data    Source code
       1              : /** \file stdMotionNode.hpp
       2              :  * \brief The MagAO-X Instrument Graph stdMotionNode header file
       3              :  *
       4              :  * \ingroup instGraph_files
       5              :  */
       6              : 
       7              : #ifndef stdMotionNode_hpp
       8              : #define stdMotionNode_hpp
       9              : 
      10              : #include "fsmNode.hpp"
      11              : 
      12              : ///
      13              : /**
      14              :  *
      15              :  * The key assumption of this node is that it should be in a valid, not-`none`, preset position
      16              :  * for its ioputs to be `on`.  It also supports triggering an alternate `on` state, which is used for
      17              :  * stages which have a continuous tracking mode (k-mirror and ADC).
      18              :  *
      19              :  * The preset is specified by an INDI property with signature `<device>.<presetPrefix>Name` where device
      20              :  * and presetPrefix are part of the configuration.  This INDI property is a switch vector.
      21              :  *
      22              :  * The device and prefix can only be set once.
      23              :  */
      24              : class stdMotionNode : public fsmNode
      25              : {
      26              : 
      27              :   protected:
      28              :     /// The prefix for preset naes.  Usually either "preset" or "filter", to which "Name" is appended.
      29              :     std::string m_presetPrefix;
      30              : 
      31              :     /// The INDI key (device.property) for the presets.  This is, say, `fwpupil.filterName`.  It is set automatically.
      32              :     std::string m_presetKey;
      33              : 
      34              :     /// The current value of the preset property.  Corresponds to the element name of the selected preset.
      35              :     std::string m_curVal;
      36              : 
      37              :     /// The current value of the put label.
      38              :     std::string m_curLabel;
      39              : 
      40              :     std::vector<std::string> m_presetPutName{ "out" };
      41              : 
      42              :     /// This sets whether the multi-put selector is on the input or the output (default)
      43              :     /** If this is a multi-put node (m_presetPutName.size() > 1) then the value of the preset switch
      44              :      * controls which input or output is on, with the others off.
      45              :      */
      46              :     ingr::ioDir m_presetDir{ ingr::ioDir::output };
      47              : 
      48              :     /// Contains the names of any puts which are always on if any are on.
      49              :     std::set<std::string> m_alwaysOn;
      50              : 
      51              :     /// Contains the names of any puts which are not automatically turned on if they are off.
      52              :     std::set<std::string> m_noAutoOn;
      53              : 
      54              :     /// The INDI key (device.property) for the switch denoting that this stage should be or should not be tracking
      55              :     std::string m_trackingReqKey;
      56              : 
      57              :     /// The element of the INDI property denoted by m_trackingReqKey to follow.
      58              :     std::string m_trackingReqElement;
      59              : 
      60              :     /// The INDI key (device.property) for the switch denoting that this stage is tracking
      61              :     std::string m_trackerKey;
      62              : 
      63              :     /// The element of the INDI property denoted by m_trackerKey to follow.
      64              :     std::string m_trackerElement;
      65              : 
      66              :     /// Flag indicating if the stage should be (true) or should not be (false, default) tracking.
      67              :     bool m_trackingReq{ false };
      68              : 
      69              :     /// Flag indicating whether or not the stage is currently tracking (default false).
      70              :     bool m_tracking{ false };
      71              : 
      72              :   public:
      73              :     /// Only c'tor.  Must be constructed with node name and a parent graph.
      74              :     stdMotionNode( const std::string  &name, /** [in] the name of this node*/
      75              :                    ingr::instGraphXML *parentGraph /** [in] the graph which this node belongs to*/ );
      76              : 
      77              :     /// Set the device name.  This can only be done once.
      78              :     /**
      79              :      * \throws
      80              :      */
      81              :     virtual void device( const std::string &dev /**< [in] */ );
      82              : 
      83              :     using fsmNode::device;
      84              : 
      85              :     virtual void presetPrefix( const std::string &pp /**< [in] */ );
      86              : 
      87              :     const std::string &presetPrefix();
      88              : 
      89              :     /// Get the current label text
      90              :     /**
      91              :      * \returns the current value of m_curLabel.
      92              :      */
      93              :     const std::string &curLabel();
      94              : 
      95              :     void presetPutName( const std::vector<std::string> &ppp /**< [in] */ );
      96              : 
      97              :     const std::vector<std::string> &presetPutName();
      98              : 
      99              :     void presetDir( const ingr::ioDir &dir /**< [in] */ );
     100              : 
     101              :     const ingr::ioDir &presetDir();
     102              : 
     103              :     void trackingReqKey( const std::string &tk /**< [in] */ );
     104              : 
     105              :     const std::string &trackingReqKey();
     106              : 
     107              :     void trackingReqElement( const std::string &te /**< [in] */ );
     108              : 
     109              :     const std::string &trackingReqElement();
     110              : 
     111              :     void trackerKey( const std::string &tk /**< [in] */ );
     112              : 
     113              :     const std::string &trackerKey();
     114              : 
     115              :     void trackerElement( const std::string &te /**< [in] */ );
     116              : 
     117              :     const std::string &trackerElement();
     118              : 
     119              :     /// INDI SetProperty callback
     120              :     virtual int handleSetProperty( const pcf::IndiProperty &ipRecv /**< [in] the received INDI property to handle*/ );
     121              : 
     122              :     virtual void togglePutsOn();
     123              : 
     124              :     virtual void togglePutsOff();
     125              : 
     126              :     void loadConfig(
     127              :         mx::app::appConfigurator &config /**< [in] the application configurator loaded with this node's options*/ );
     128              : };
     129              : 
     130           19 : inline stdMotionNode::stdMotionNode( const std::string &name, ingr::instGraphXML *parentGraph )
     131           55 :     : fsmNode( name, parentGraph )
     132              : {
     133           18 : }
     134              : 
     135            7 : inline void stdMotionNode::device( const std::string &dev )
     136              : {
     137              :     // This will enforce the one-time only rule
     138            7 :     fsmNode::device( dev );
     139              : 
     140              :     // If presetPrefix is set, then we can make the key
     141            6 :     if( m_presetPrefix != "" )
     142              :     {
     143            1 :         m_presetKey = m_device + "." + m_presetPrefix + "Name";
     144            1 :         key( m_presetKey );
     145              :     }
     146            6 : }
     147              : 
     148            6 : inline void stdMotionNode::presetPrefix( const std::string &pp )
     149              : {
     150              :     // Set it one time only
     151            6 :     if( m_presetPrefix != "" && pp != m_presetPrefix )
     152              :     {
     153              :         std::string msg =
     154            1 :             "stdMotionNode::presetPrefix: attempt to change preset prefix from " + m_presetPrefix + " to " + pp;
     155            1 :         msg += " at ";
     156            1 :         msg += __FILE__;
     157            1 :         msg += " " + std::to_string( __LINE__ );
     158            1 :         throw std::runtime_error( msg );
     159            1 :     }
     160              : 
     161            5 :     m_presetPrefix = pp;
     162              : 
     163              :     // If device has been set then we can create the key
     164            5 :     if( m_device != "" )
     165              :     {
     166            4 :         m_presetKey = m_device + "." + m_presetPrefix + "Name";
     167            4 :         key( m_presetKey );
     168              :     }
     169            5 : }
     170              : 
     171            2 : inline const std::string &stdMotionNode::presetPrefix()
     172              : {
     173            2 :     return m_presetPrefix;
     174              : }
     175              : 
     176           11 : inline const std::string &stdMotionNode::curLabel()
     177              : {
     178           11 :     return m_curLabel;
     179              : }
     180              : 
     181            3 : inline void stdMotionNode::presetPutName( const std::vector<std::string> &ppp )
     182              : {
     183            3 :     m_presetPutName = ppp;
     184            3 : }
     185              : 
     186            5 : inline const std::vector<std::string> &stdMotionNode::presetPutName()
     187              : {
     188            5 :     return m_presetPutName;
     189              : }
     190              : 
     191           12 : inline void stdMotionNode::presetDir( const ingr::ioDir &dir )
     192              : {
     193           12 :     m_presetDir = dir;
     194           12 : }
     195              : 
     196            2 : inline const ingr::ioDir &stdMotionNode::presetDir()
     197              : {
     198            2 :     return m_presetDir;
     199              : }
     200              : 
     201            4 : inline void stdMotionNode::trackingReqKey( const std::string &tk )
     202              : {
     203            4 :     m_trackingReqKey = tk;
     204              : 
     205            4 :     if( m_trackingReqKey != "" )
     206              :     {
     207            2 :         key( m_trackingReqKey );
     208              :     }
     209            4 : }
     210              : 
     211            1 : inline const std::string &stdMotionNode::trackingReqKey()
     212              : {
     213            1 :     return m_trackingReqKey;
     214              : }
     215              : 
     216            4 : inline void stdMotionNode::trackingReqElement( const std::string &te )
     217              : {
     218            4 :     m_trackingReqElement = te;
     219            4 : }
     220              : 
     221            1 : inline const std::string &stdMotionNode::trackingReqElement()
     222              : {
     223            1 :     return m_trackingReqElement;
     224              : }
     225              : 
     226            4 : inline void stdMotionNode::trackerKey( const std::string &tk )
     227              : {
     228            4 :     m_trackerKey = tk;
     229              : 
     230            4 :     if( m_trackerKey != "" )
     231              :     {
     232            2 :         key( m_trackerKey );
     233              :     }
     234            4 : }
     235              : 
     236            2 : inline const std::string &stdMotionNode::trackerKey()
     237              : {
     238            2 :     return m_trackerKey;
     239              : }
     240              : 
     241            4 : inline void stdMotionNode::trackerElement( const std::string &te )
     242              : {
     243            4 :     m_trackerElement = te;
     244            4 : }
     245              : 
     246            2 : inline const std::string &stdMotionNode::trackerElement()
     247              : {
     248            2 :     return m_trackerElement;
     249              : }
     250              : 
     251           14 : inline int stdMotionNode::handleSetProperty( const pcf::IndiProperty &ipRecv )
     252              : {
     253           14 :     int rv = fsmNode::handleSetProperty( ipRecv );
     254              : 
     255           14 :     if( rv < 0 )
     256              :     {
     257            0 :         return rv;
     258              :     }
     259              : 
     260           14 :     if( ipRecv.createUniqueKey() == m_trackingReqKey )
     261              :     {
     262            3 :         if( ipRecv.find( m_trackingReqElement ) )
     263              :         {
     264            3 :             if( ipRecv[m_trackingReqElement].getSwitchState() == pcf::IndiElement::On )
     265              :             {
     266            1 :                 if( !m_trackingReq )
     267              :                 {
     268            1 :                     ++m_changes;
     269              :                 }
     270              : 
     271            1 :                 m_trackingReq = true;
     272              :             }
     273              :             else
     274              :             {
     275            2 :                 if( m_trackingReq )
     276              :                 {
     277            1 :                     ++m_changes;
     278              :                 }
     279            2 :                 m_trackingReq = false;
     280              :             }
     281              :         }
     282              :     }
     283           11 :     else if( ipRecv.createUniqueKey() == m_trackerKey )
     284              :     {
     285            3 :         if( ipRecv.find( m_trackerElement ) )
     286              :         {
     287            3 :             if( ipRecv[m_trackerElement].getSwitchState() == pcf::IndiElement::On )
     288              :             {
     289            1 :                 if( !m_tracking )
     290              :                 {
     291            1 :                     ++m_changes;
     292              :                 }
     293              : 
     294            1 :                 m_tracking = true;
     295              :             }
     296              :             else
     297              :             {
     298            2 :                 if( m_tracking )
     299              :                 {
     300            1 :                     ++m_changes;
     301              :                 }
     302            2 :                 m_tracking = false;
     303              :             }
     304              :         }
     305              :     }
     306            8 :     else if( ipRecv.createUniqueKey() == m_presetKey )
     307              :     {
     308            5 :         if( m_node != nullptr )
     309              :         {
     310            5 :             bool nothingIsOn = true;
     311           15 :             for( auto &&it : ipRecv.getElements() )
     312              :             {
     313           10 :                 if( it.second.getSwitchState() == pcf::IndiElement::On )
     314              :                 {
     315            4 :                     if( m_curVal != it.second.getName() && !m_tracking ) // we only update if not tracking
     316              :                     {
     317            4 :                         ++m_changes;
     318              :                     }
     319              : 
     320            4 :                     m_curVal    = it.second.getName();
     321            4 :                     nothingIsOn = false;
     322              :                 }
     323              :             }
     324              : 
     325            5 :             if( nothingIsOn )
     326              :             {
     327            1 :                 if( m_curVal != "" && !m_tracking ) // we only update if not tracking
     328              :                 {
     329            1 :                     ++m_changes;
     330              :                 }
     331            1 :                 m_curVal = "";
     332              :             }
     333              :         }
     334              :     }
     335              : 
     336           14 :     if( m_changes > 0 )
     337              :     {
     338           12 :         m_changes = 0;
     339              : 
     340           12 :         if( m_trackingReq )
     341              :         {
     342            3 :             if( m_tracking &&
     343            2 :                 ( m_state == MagAOX::app::stateCodes::READY || m_state == MagAOX::app::stateCodes::OPERATING ) )
     344              :             {
     345            2 :                 togglePutsOn();
     346              :             }
     347              :             else
     348              :             { // Either we aren't tracking or we aren't READY || OPERATING
     349            1 :                 togglePutsOff();
     350              :             }
     351              :         }
     352              :         else
     353              :         {
     354            9 :             if( m_state != MagAOX::app::stateCodes::READY || m_tracking || m_curVal == "none" || m_curVal == "" )
     355              :             {
     356            6 :                 togglePutsOff();
     357              :             }
     358              :             else
     359              :             {
     360            3 :                 togglePutsOn();
     361              :             }
     362              :         }
     363              :     }
     364              : 
     365           14 :     return 0;
     366              : }
     367              : 
     368            5 : inline void stdMotionNode::togglePutsOn()
     369              : {
     370            5 :     if( m_node == nullptr || !m_parentGraph || !m_node->auxDataValid() )
     371              :     {
     372            0 :         return;
     373              :     }
     374              : 
     375            5 :     if( m_trackingReq )
     376              :     {
     377            2 :         if( m_tracking )
     378              :         {
     379            2 :             m_curLabel = "tracking";
     380            4 :             m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, "tracking" );
     381            8 :             m_parentGraph->valueExtra( m_node->name(), "state", "tracking" );
     382            2 :             xigNode::togglePutsOn();
     383              :         }
     384              :         else
     385              :         {
     386            0 :             m_curLabel = "not tracking";
     387            0 :             m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, "not tracking" );
     388            0 :             m_parentGraph->valueExtra( m_node->name(), "state", "not tracking" );
     389            0 :             m_parentGraph->stateChange();
     390              :         }
     391              :     }
     392            3 :     else if( m_state == MagAOX::app::stateCodes::READY )
     393              :     {
     394            3 :         m_curLabel = m_curVal;
     395              : 
     396            6 :         m_parentGraph->valueExtra( m_node->name(), "state", m_curLabel );
     397              : 
     398            3 :         if( m_presetPutName.size() == 1 ) // There's only one put, it's just on or off with a value
     399              :         {
     400            3 :             m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, m_curVal );
     401            3 :             xigNode::togglePutsOn();
     402              :         }
     403              :         else // There is more than one put, and which one is on is selected by the value of the switch
     404              :         {
     405            0 :             if( m_presetDir == ingr::ioDir::output )
     406              :             {
     407              :                 ingr::instIOPut *pptr; // We get this pointer using the node accessors
     408              :                                        // which throw if there's a nullptr
     409              : 
     410              :                 // first deal with the single input
     411              :                 try
     412              :                 {
     413            0 :                     pptr = m_node->inputs().begin()->second;
     414              :                 }
     415            0 :                 catch( ... )
     416              :                 {
     417            0 :                     return;
     418            0 :                 }
     419              : 
     420              :                 // the single node is always on if any are on
     421            0 :                 pptr->enabled( true );
     422            0 :                 pptr->state( ingr::putState::on );
     423              : 
     424            0 :                 ingr::putState inst = pptr->state();
     425            0 :                 if( inst != ingr::putState::on )
     426              :                 {
     427            0 :                     inst = ingr::putState::waiting;
     428              :                 }
     429              : 
     430              :                 // Now deal with the many
     431            0 :                 for( auto s : m_presetPutName )
     432              :                 {
     433              :                     try
     434              :                     {
     435            0 :                         pptr = m_node->output( s );
     436              :                     }
     437            0 :                     catch( ... )
     438              :                     {
     439            0 :                         return;
     440            0 :                     }
     441              : 
     442            0 :                     if( s == m_curVal || m_alwaysOn.count( s ) == 1 )
     443              :                     {
     444            0 :                         pptr->enabled( true );
     445            0 :                         pptr->state( inst );
     446              :                     }
     447              :                     else
     448              :                     {
     449            0 :                         pptr->state( ingr::putState::off );
     450              : 
     451            0 :                         if( m_noAutoOn.count( s ) == 1 ) // if we turn it off, we disable it
     452              :                         {
     453            0 :                             pptr->enabled( false );
     454              :                         }
     455              :                     }
     456            0 :                 }
     457              :             }
     458              :             else // m_presetDir == ingr::ioDir::input )
     459              :             {
     460              :                 ingr::instIOPut *pptr; // We get this pointer using the node accessors
     461              :                                        // which throw if there's a nullptr
     462              : 
     463              :                 // first deal with the single input
     464              :                 try
     465              :                 {
     466            0 :                     pptr = m_node->outputs().begin()->second;
     467              :                 }
     468            0 :                 catch( ... )
     469              :                 {
     470            0 :                     return;
     471            0 :                 }
     472              : 
     473              :                 // the single node is always on if any are on
     474            0 :                 pptr->enabled( true );
     475            0 :                 pptr->state( ingr::putState::on );
     476              : 
     477              :                 // Now deal with the many
     478            0 :                 for( auto s : m_presetPutName )
     479              :                 {
     480              :                     try
     481              :                     {
     482            0 :                         pptr = m_node->input( s );
     483              :                     }
     484            0 :                     catch( ... )
     485              :                     {
     486            0 :                         return;
     487            0 :                     }
     488              : 
     489            0 :                     if( s == m_curVal || m_alwaysOn.count( s ) == 1 )
     490              :                     {
     491            0 :                         pptr->enabled( true );
     492            0 :                         pptr->state( ingr::putState::on );
     493              :                     }
     494              :                     else
     495              :                     {
     496            0 :                         pptr->state( ingr::putState::off );
     497              : 
     498            0 :                         if( m_noAutoOn.count( s ) == 1 ) // if we turn it off, we disable it
     499              :                         {
     500            0 :                             pptr->enabled( false );
     501              :                         }
     502              :                     }
     503            0 :                 }
     504              :             }
     505              :         }
     506            3 :         m_parentGraph->stateChange();
     507              :     }
     508              : 
     509            5 :     return;
     510              : }
     511              : 
     512            7 : inline void stdMotionNode::togglePutsOff()
     513              : {
     514            7 :     if( m_node == nullptr || !m_parentGraph || !m_node->auxDataValid() )
     515              :     {
     516            0 :         return;
     517              :     }
     518              : 
     519            7 :     if( m_tracking ) // regardless of whether required, if tracking this is our state
     520              :     {
     521            1 :         m_curLabel = "tracking";
     522            2 :         m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, "tracking" );
     523            5 :         m_parentGraph->valueExtra( m_node->name(), "state", "tracking" );
     524              :     }
     525            6 :     else if( m_trackingReq ) // we can only be "not tracking" if tracking is required
     526              :     {
     527            1 :         m_curLabel = "not tracking";
     528            2 :         m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, "not tracking" );
     529            5 :         m_parentGraph->valueExtra( m_node->name(), "state", "not tracking" );
     530              :     }
     531            5 :     else if( m_presetPutName.size() == 1 ) // otherwise, if we have a single node it's off
     532              :     {
     533            5 :         m_curLabel = "off";
     534           10 :         m_parentGraph->valuePut( name(), m_presetPutName[0], m_presetDir, "off" );
     535           25 :         m_parentGraph->valueExtra( m_node->name(), "state", "---" );
     536              :     }
     537              :     else
     538              :     {
     539              :         // We don't change labels if m_presetPutName.size() > 1
     540            0 :         m_parentGraph->valueExtra( m_node->name(), "state", "---" );
     541              :     }
     542              : 
     543              :     // replace xigNode::togglePutsOff() so we can check for always-on
     544              : 
     545            7 :     for( auto &&iput : m_node->inputs() )
     546              :     {
     547            0 :         if( m_alwaysOn.count( iput.second->name() ) > 0 )
     548              :         {
     549            0 :             continue;
     550              :         }
     551              : 
     552              :         // iput.second->enabled(false);
     553            0 :         iput.second->state( ingr::putState::off );
     554              :     }
     555              : 
     556            7 :     for( auto &&oput : m_node->outputs() )
     557              :     {
     558            0 :         if( m_alwaysOn.count( oput.second->name() ) > 0 )
     559              :         {
     560            0 :             continue;
     561              :         }
     562              :         // oput.second->enabled(false);
     563            0 :         oput.second->state( ingr::putState::off );
     564              : 
     565            0 :         if( m_noAutoOn.count( oput.second->name() ) == 1 ) // if we turn it off, we disable it
     566              :         {
     567            0 :             oput.second->enabled( false );
     568              :         }
     569              :     }
     570              : }
     571              : 
     572           17 : inline void stdMotionNode::loadConfig( mx::app::appConfigurator &config )
     573              : {
     574           17 :     if( !m_parentGraph )
     575              :     {
     576            5 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "parent graph is null" );
     577            1 :         throw std::runtime_error( msg );
     578            1 :     }
     579              : 
     580           16 :     std::string type;
     581           16 :     config.configUnused( type, mx::app::iniFile::makeKey( name(), "type" ) );
     582              : 
     583           16 :     if( type != "stdMotion" )
     584              :     {
     585           15 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "node type is not stdMotion" );
     586            3 :         throw std::runtime_error( msg );
     587            3 :     }
     588              : 
     589           13 :     std::string dev = name();
     590           26 :     config.configUnused( dev, mx::app::iniFile::makeKey( name(), "device" ) );
     591              : 
     592           26 :     std::string prePrefix = "preset";
     593           26 :     config.configUnused( prePrefix, mx::app::iniFile::makeKey( name(), "presetPrefix" ) );
     594              : 
     595           26 :     std::string preDir = "output";
     596           13 :     config.configUnused( preDir, mx::app::iniFile::makeKey( name(), "presetDir" ) );
     597              : 
     598           13 :     if( preDir == "input" )
     599              :     {
     600            1 :         presetDir( ingr::ioDir::input );
     601              :     }
     602           12 :     else if( preDir == "output" )
     603              :     {
     604           11 :         presetDir( ingr::ioDir::output );
     605              :     }
     606              :     else
     607              :     {
     608            5 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "invalid presetDir (must be input or output)" );
     609            1 :         throw std::runtime_error( msg );
     610            1 :     }
     611              : 
     612           36 :     std::vector<std::string> prePutName( { "out" } );
     613           12 :     config.configUnused( prePutName, mx::app::iniFile::makeKey( name(), "presetPutName" ) );
     614           12 :     if( prePutName.size() == 0 )
     615              :     {
     616            5 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "presetPutName can't be empty" );
     617            1 :         throw std::runtime_error( msg );
     618            1 :     }
     619              : 
     620           11 :     std::vector<std::string> alwaysOn;
     621           11 :     config.configUnused( alwaysOn, mx::app::iniFile::makeKey( name(), "alwaysOn" ) );
     622              :     try
     623              :     {
     624           11 :         for( auto &ao : alwaysOn )
     625              :         {
     626            0 :             m_alwaysOn.insert( ao );
     627              :         }
     628              :     }
     629            0 :     catch( const std::exception &e )
     630              :     {
     631            0 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "exception from insert in m_alwaysOn" );
     632            0 :         msg += ":";
     633            0 :         msg += e.what();
     634            0 :         throw std::runtime_error( msg );
     635            0 :     }
     636              : 
     637           11 :     std::vector<std::string> noAutoOn;
     638           11 :     config.configUnused( noAutoOn, mx::app::iniFile::makeKey( name(), "noAutoOn" ) );
     639              :     try
     640              :     {
     641           11 :         for( auto &ao : noAutoOn )
     642              :         {
     643            0 :             m_noAutoOn.insert( ao );
     644              :         }
     645              :     }
     646            0 :     catch( const std::exception &e )
     647              :     {
     648            0 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig", "exception from insert in m_noAutoOn" );
     649            0 :         msg += ":";
     650            0 :         msg += e.what();
     651            0 :         throw std::runtime_error( msg );
     652            0 :     }
     653              : 
     654           11 :     std::string trackReqKey;
     655           11 :     config.configUnused( trackReqKey, mx::app::iniFile::makeKey( name(), "trackingReqKey" ) );
     656              : 
     657           11 :     std::string trackReqEl;
     658           11 :     config.configUnused( trackReqEl, mx::app::iniFile::makeKey( name(), "trackingReqElement" ) );
     659              : 
     660              :     // Check if both are set
     661           11 :     if( ( trackReqKey == "" && trackReqEl != "" ) || ( trackReqKey != "" && trackReqEl == "" ) )
     662              :     {
     663           10 :         std::string msg = XIGN_EXCEPTION( "stdMotionNode::loadConfig",
     664              :                                           "trackingReqKey and trackingReqElement must both be provided" );
     665            2 :         throw std::runtime_error( msg );
     666            2 :     }
     667              : 
     668            9 :     std::string trackKey;
     669            9 :     config.configUnused( trackKey, mx::app::iniFile::makeKey( name(), "trackerKey" ) );
     670              : 
     671            9 :     std::string trackEl;
     672            9 :     config.configUnused( trackEl, mx::app::iniFile::makeKey( name(), "trackerElement" ) );
     673              : 
     674              :     // Check if both are set
     675            9 :     if( ( trackKey == "" && trackEl != "" ) || ( trackKey != "" && trackEl == "" ) )
     676              :     {
     677              :         std::string msg =
     678           10 :             XIGN_EXCEPTION( "stdMotionNode::loadConfig", "trackingKey and trackingElement must both be provided" );
     679            2 :         throw std::runtime_error( msg );
     680            2 :     }
     681              : 
     682              :     // This will catch the case where one or the other pair was set, but not both
     683            7 :     if( ( trackKey == "" && trackReqKey != "" ) || ( trackKey != "" && trackReqKey == "" ) )
     684              :     {
     685              :         std::string msg =
     686           10 :             XIGN_EXCEPTION( "stdMotionNode::loadConfig", "trackingReqKey and trackerKey must both be provided" );
     687            2 :         throw std::runtime_error( msg );
     688            2 :     }
     689              : 
     690            5 :     device( dev );
     691            4 :     presetPrefix( prePrefix );
     692            3 :     presetPutName( prePutName );
     693            3 :     trackingReqKey( trackReqKey );
     694            3 :     trackingReqElement( trackReqEl );
     695            3 :     trackerKey( trackKey );
     696            3 :     trackerElement( trackEl );
     697          135 : }
     698              : 
     699              : #endif // stdMotionNode_hpp
        

Generated by: LCOV version 2.0-1