API
 
Loading...
Searching...
No Matches
fsmNode.hpp
Go to the documentation of this file.
1/** \file fsmNode.hpp
2 * \brief The MagAO-X Instrument Graph fsmNode header file
3 *
4 * \ingroup instGraph_files
5 */
6
7#ifndef fsmNode_hpp
8#define fsmNode_hpp
9
10#include "xigNode.hpp"
11
13{
14 passive, /**< Only monitor and report FSM state, don't change puts*/
15 threshOff, /**< If state is not in one of the specified states, turn puts off*/
16 active, /**< If state is in one of the specified states, turn puts on. Turn them off otherwise.*/
17 unknown /**< Unknown action, generally an error. */
18};
19
21{
22 if( action == fsmNodeActionT::passive )
23 {
24 return "passive";
25 }
26 else if( action == fsmNodeActionT::threshOff )
27 {
28 return "threshOff";
29 }
30 else if( action == fsmNodeActionT::active )
31 {
32 return "active";
33 }
34 else
35 {
36 return "";
37 }
38}
39
40fsmNodeActionT fsmNodeActionTFromString( const std::string &action )
41{
42 if( action == "passive" )
43 {
45 }
46 else if( action == "threshOff" )
47 {
49 }
50 else if( action == "active" )
51 {
53 }
54 else
55 {
57 }
58}
59
60/// Implementation of an instGraph node interface for a MagAO-X Finite State Machine (FSM)
61/** This class is interraces to a standard FSM. It tracks the FSM state INDI property
62 * and keeps its internal state updated.
63 *
64 * Whether it impacts ioput status depends on the `action` specified.
65 *
66 */
67
68class fsmNode : public xigNode
69{
70
72
73 protected:
74 std::string m_device; ///< The INDI device name. Defaults to the node name set on construction.
75 std::string m_fsmPropName{ "fsm" }; ///< The INDI property name for the FSM, normally "fsm".
76 std::string m_fsmElName{ "state" }; ///< The INDI property element name for the FSM, normally "state".
77
78 std::string m_fsmKey; ///< The unique INDI key, `<device>.<fsmPropName>`, for the FSM state INDI property.
79
81
82 std::vector<stateCodeT> m_targetStates;
83
84 stateCodeT m_state{ -999 }; ///< The numerical code of the current state.
85 std::string m_stateStr; ///< The string name of the current state.
86
87 bool m_stateOnTarget{ false }; ///< Flag indicating if the current state matches any of the target states.
88
89 public:
90 /// Constructor.
91 /**
92 * Default c'tor is deleted in base classs. Must supply both node name and a parentGraph with a node with the same
93 * name in it.
94 */
95 fsmNode( const std::string &name, /**< [in] the name of the node */
96 ingr::instGraphXML *parentGraph /**< [in] the parent instGraph */
97 );
98
99 /// Set the device name
100 /**
101 * Derived classes may implement this to add extra logic. The device name defaults
102 * to the node name on construction.
103 */
104 virtual void device( const std::string &dev /**< [in] the new device name */ );
105
106 /// Get the device name
107 /**
108 * \return the current value of m_device
109 */
110 const std::string &device() const;
111
112 /// Set the fsm property name
113 /**
114 * Derived classes may implement this to add extra logic. The fsm property name defaults
115 * to "fsm"
116 *
117 * This can only be called before device is set
118 */
119 virtual void fsmPropName( const std::string &pn /**< [in] the new property name */ );
120
121 /// Get the fsm property name
122 /**
123 * \return the current value of m_fsmPropName
124 */
125 const std::string &fsmPropName() const;
126
127 /// Set the fsm element name
128 /**
129 * Derived classes may implement this to add extra logic. The fsm element name defaults
130 * to "state"
131 *
132 * This can be called at any time
133 */
134 virtual void fsmElName( const std::string &en /**< [in] the new element name */ );
135
136 /// Get the fsm element name
137 /**
138 * \return the current value of m_fsmElName
139 */
140 const std::string &fsmElName() const;
141
142 /// Get the FSM unique key
143 /**
144 * \return the current value of m_fsmKey
145 */
146 const std::string &fsmKey() const;
147
148 /// Get the action
149 /**
150 * \return the current value of m_fsmAction
151 */
153
154 /// Set the action
155 void fsmAction( fsmNodeActionT act );
156
157 /// Get the target states
158 /**
159 * \return the current value of m_targetStates
160 */
161 const std::vector<stateCodeT> &targetStates() const;
162
163 /// Load this specific node's settings from an application configuration
164 /**
165 * Verifies that the named node is an fsmNode.
166 *
167 * \throws std::runtime_error if m_parentGraph is nullptr or the config is not for an fsmNode.
168 */
169 void loadConfig( mx::app::appConfigurator &config /**< [in] the application configurator
170 loaded with this node's options*/ );
171
172 protected:
173 /// Load this specific node's settings from an application configuration of a derived class
174 /**
175 * Does not cerifies that the named node is an fsmNode.
176 *
177 */
178 void loadConfigDerived( mx::app::appConfigurator &config /**< [in] the application configurator
179 loaded with this node's options*/ );
180
181 public:
182 /// INDI SetProperty callback
183 virtual int handleSetProperty( const pcf::IndiProperty &ipRecv /**< [in] the received INDI property to handle*/ );
184
185 /// INDI SetProperty callback with indication if action was taken
186 /** The possible actions are determined by m_fsmAction. If the action was taken then the caller
187 * should return without further processing.
188 *
189 */
190 virtual int handleSetProperty( bool &actionTaken, /** < [out] indicates if action taken (true). */
191 const pcf::IndiProperty &ipRecv /**< [in] the received INDI property to handle*/ );
192
193 public:
194 virtual void updateGUI();
195};
196
197inline fsmNode::fsmNode( const std::string &name, ingr::instGraphXML *parentGraph ) : xigNode( name, parentGraph )
198{
199}
200
201inline void fsmNode::device( const std::string &dev )
202{
203 if( m_device != "" && dev != m_device )
204 {
205 std::string msg = "fsmNode::device attempt to change device name from " + m_device + " to " + dev;
206 msg += " in " + name();
207 msg += " at ";
208 msg += __FILE__;
209 msg += " " + std::to_string( __LINE__ );
210 throw std::runtime_error( msg );
211 }
212
213 if( dev == "" )
214 {
215 std::string msg = "fsmNode::device attempt to set empty device name in " + name();
216 msg += " at ";
217 msg += __FILE__;
218 msg += " " + std::to_string( __LINE__ );
219 throw std::runtime_error( msg );
220 }
221
222 m_device = dev;
224
225 key( m_fsmKey );
226}
227
228inline const std::string &fsmNode::device() const
229{
230 return m_device;
231}
232
233inline void fsmNode::fsmPropName( const std::string &pn )
234{
235 if( m_fsmPropName != "" && m_device != "" )
236 {
237 std::string msg = "fsmNode::fsmPropName attempt to change fsmPropName name from " + m_fsmPropName + " to " + pn;
238 msg += " in " + name();
239 msg += " at ";
240 msg += __FILE__;
241 msg += " " + std::to_string( __LINE__ );
242 throw std::runtime_error( msg );
243 }
244
245 if( m_device != "" )
246 {
247 std::string msg = "fsmNode::fsmPropName attempt to set propName after device already set " + name();
248 msg += " at ";
249 msg += __FILE__;
250 msg += " " + std::to_string( __LINE__ );
251 throw std::runtime_error( msg );
252 }
253
254 if( pn == "" )
255 {
256 std::string msg = "fsmNode::fsmPropName attempt to set propName to empty " + name();
257 msg += " at ";
258 msg += __FILE__;
259 msg += " " + std::to_string( __LINE__ );
260 throw std::runtime_error( msg );
261 }
262
263 m_fsmPropName = pn;
264}
265
266inline const std::string &fsmNode::fsmPropName() const
267{
268 return m_fsmPropName;
269}
270
271inline void fsmNode::fsmElName( const std::string &en )
272{
273 if( en == "" )
274 {
275 std::string msg = "fsmNode::fsmElName attempt to set elName to empty " + name();
276 msg += " at ";
277 msg += __FILE__;
278 msg += " " + std::to_string( __LINE__ );
279 throw std::runtime_error( msg );
280 }
281
282 m_fsmElName = en;
283}
284
285inline const std::string &fsmNode::fsmElName() const
286{
287 return m_fsmElName;
288}
289
290const std::string &fsmNode::fsmKey() const
291{
292 return m_fsmKey;
293}
294
296{
297 return m_fsmAction;
298}
299
301{
302 m_fsmAction = act;
303}
304
305const std::vector<fsmNode::stateCodeT> &fsmNode::targetStates() const
306{
307 return m_targetStates;
308}
309
310inline void fsmNode::loadConfig( mx::app::appConfigurator &config )
311{
312 if( !m_parentGraph )
313 {
314 std::string msg = "fsmNode::loadConfig: parent graph is null";
315 msg += " at ";
316 msg += __FILE__;
317 msg += " " + std::to_string( __LINE__ );
318 throw std::runtime_error( msg );
319 }
320
321 std::string type;
322 config.configUnused( type, mx::app::iniFile::makeKey( name(), "type" ) );
323
324 if( type != "fsm" )
325 {
326 std::string msg = "fsmNode::loadConfig: node type is not fsmNode";
327 msg += " at ";
328 msg += __FILE__;
329 msg += " " + std::to_string( __LINE__ );
330 throw std::runtime_error( msg );
331 }
332
333 loadConfigDerived( config );
334}
335
336inline void fsmNode::loadConfigDerived( mx::app::appConfigurator &config )
337{
338 //This must be first
339 std::string propName = fsmPropName();
340 config.configUnused( propName, mx::app::iniFile::makeKey( name(), "fsmPropName" ) );
341 fsmPropName( propName );
342
343 std::string dev = name();
344 config.configUnused( dev, mx::app::iniFile::makeKey( name(), "device" ) );
345 device( dev );
346
347 std::string elName = fsmElName();
348 config.configUnused( elName, mx::app::iniFile::makeKey( name(), "fsmElName" ) );
349 fsmElName( elName );
350
351 std::string action = fsmNodeActionT2String( m_fsmAction );
352 config.configUnused( action, mx::app::iniFile::makeKey( name(), "fsmAction" ) );
354
356 {
357 std::string msg = XIGN_EXCEPTION( "fsmNode::loadConfig", "fsmAction is unknown" );
358 throw std::runtime_error( msg );
359 }
360
361 std::vector<std::string> targetStates;
362 config.configUnused( targetStates, mx::app::iniFile::makeKey( name(), "targetStates" ) );
363 m_targetStates.resize( targetStates.size() );
364 for( size_t n = 0; n < targetStates.size(); ++n )
365 {
367 }
368
369 if( m_parentGraph && m_node )
370 {
371 m_parentGraph->valueExtra( m_node->name(), "state", "" );
372 }
373}
374
375inline int fsmNode::handleSetProperty( const pcf::IndiProperty &ipRecv )
376{
377 bool actionTaken;
378 return handleSetProperty( actionTaken, ipRecv );
379}
380
381inline int fsmNode::handleSetProperty( bool &actionTaken, const pcf::IndiProperty &ipRecv )
382{
383 if( ipRecv.createUniqueKey() != m_fsmKey )
384 {
385 actionTaken = false;
386 return 0;
387 }
388
389 if( !ipRecv.find( m_fsmElName ) )
390 {
391 actionTaken = false;
392 return 0;
393 }
394
395 m_stateStr = ipRecv[m_fsmElName].get<std::string>();
396
398
399 if( state != m_state )
400 {
401 ++m_changes;
402 }
403
404 m_state = state;
405
406 m_parentGraph->valueExtra( m_node->name(), "fsmstate", m_stateStr );
407
408 bool stateOnTarget = false;
409
410 for( auto state : m_targetStates )
411 {
412 if( m_state == state )
413 {
414 stateOnTarget = true;
415 break;
416 }
417 }
418 m_stateOnTarget = stateOnTarget;
419
421 {
422 if( m_stateOnTarget )
423 {
424 actionTaken = false;
425 return 0;
426 }
427 else
428 {
430 actionTaken = true;
431 return 0;
432 }
433 }
435 {
436 if( m_stateOnTarget )
437 {
438 togglePutsOn();
439 actionTaken = true;
440 return 0;
441 }
442 else
443 {
445 actionTaken = true;
446 return 0;
447 }
448 }
449 else // m_fsmAction == fsmNodeActionT::passive
450 {
451 actionTaken = false;
452 return 0;
453 }
454}
455
457{
458}
459
460#endif // fsmNode_hpp
Implementation of an instGraph node interface for a MagAO-X Finite State Machine (FSM)
Definition fsmNode.hpp:69
const std::string & device() const
Get the device name.
Definition fsmNode.hpp:228
virtual void updateGUI()
Definition fsmNode.hpp:456
virtual int handleSetProperty(const pcf::IndiProperty &ipRecv)
INDI SetProperty callback.
Definition fsmNode.hpp:375
const std::string & fsmPropName() const
Get the fsm property name.
Definition fsmNode.hpp:266
const std::string & fsmElName() const
Get the fsm element name.
Definition fsmNode.hpp:285
std::vector< stateCodeT > m_targetStates
Definition fsmNode.hpp:82
const std::vector< stateCodeT > & targetStates() const
Get the target states.
Definition fsmNode.hpp:305
fsmNodeActionT m_fsmAction
Definition fsmNode.hpp:80
stateCodeT m_state
The numerical code of the current state.
Definition fsmNode.hpp:84
std::string m_device
The INDI device name. Defaults to the node name set on construction.
Definition fsmNode.hpp:74
bool m_stateOnTarget
Flag indicating if the current state matches any of the target states.
Definition fsmNode.hpp:87
MagAOX::app::stateCodes::stateCodeT stateCodeT
Definition fsmNode.hpp:71
std::string m_fsmKey
The unique INDI key, <device>.<fsmPropName>, for the FSM state INDI property.
Definition fsmNode.hpp:78
std::string m_fsmPropName
The INDI property name for the FSM, normally "fsm".
Definition fsmNode.hpp:75
std::string m_fsmElName
The INDI property element name for the FSM, normally "state".
Definition fsmNode.hpp:76
std::string m_stateStr
The string name of the current state.
Definition fsmNode.hpp:85
fsmNodeActionT fsmAction() const
Get the action.
Definition fsmNode.hpp:295
void loadConfig(mx::app::appConfigurator &config)
Load this specific node's settings from an application configuration.
Definition fsmNode.hpp:310
void loadConfigDerived(mx::app::appConfigurator &config)
Load this specific node's settings from an application configuration of a derived class.
Definition fsmNode.hpp:336
const std::string & fsmKey() const
Get the FSM unique key.
Definition fsmNode.hpp:290
fsmNode(const std::string &name, ingr::instGraphXML *parentGraph)
Constructor.
Definition fsmNode.hpp:197
Implementation of basic instGraph node interface for MagAO-X.
Definition xigNode.hpp:31
void key(const std::string &nkey)
Add a key to the set.
Definition xigNode.hpp:116
ingr::instNode * m_node
The underlying instGraph node.
Definition xigNode.hpp:37
virtual void togglePutsOn()
Change the state of all inputs and all outputs to on.
Definition xigNode.hpp:126
int m_changes
Counter that can be incremented when changes are detected. Set to 0 when graph is updated.
Definition xigNode.hpp:39
ingr::instGraphXML * m_parentGraph
The parent instGraph that this node is a part of.
Definition xigNode.hpp:35
std::string name()
Get the name of this node.
Definition xigNode.hpp:106
virtual void togglePutsOff()
Change the state of all inputs and all outputs to off.
Definition xigNode.hpp:141
fsmNodeActionT fsmNodeActionTFromString(const std::string &action)
Definition fsmNode.hpp:40
fsmNodeActionT
Definition fsmNode.hpp:13
std::string fsmNodeActionT2String(fsmNodeActionT action)
Definition fsmNode.hpp:20
static stateCodeT str2CodeFast(const std::string &stateStr)
Get the stateCode corresponding to an ASCII string with minimal checks.
int16_t stateCodeT
The type of the state code.
static stateCodeT str2Code(const std::string &stateStr)
Get the stateCode corresponding to an ASCII string.
The base MagAO-X instGraph node header file.
#define XIGN_EXCEPTION(src, expl)
Definition xigNode.hpp:24