Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
EventLogger.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_EventLogger_h_ 00003 #define INCLUDED_EventLogger_h_ 00004 00005 #include "ControlBase.h" 00006 #include "Events/EventListener.h" 00007 #include <fstream> 00008 #include <set> 00009 #include <queue> 00010 #include <stack> 00011 00012 class FilterBankGenerator; 00013 class BehaviorBase; 00014 class StateNode; 00015 /*! @cond INTERNAL */ 00016 // libxml2 forward declarations 00017 extern "C" { 00018 struct _xmlNode; 00019 struct _xmlDoc; 00020 struct _xmlAttr; 00021 typedef _xmlNode xmlNode; 00022 typedef _xmlDoc xmlDoc; 00023 typedef _xmlAttr xmlAttr; 00024 } 00025 /*! @endcond */ 00026 00027 //! allows logging of events to the console or a file, also provides some remote logging facilities over #logSocket, required by Storyboard tool 00028 /*! Users' behaviors can call logMessage(), logImage(), and logWebcam() to insert the corresponding data into #logSocket via an XML 'event' node. 00029 * 00030 * The protocol used with #logSocket is: 00031 * - '<tt>list</tt>' - send list of all instantiated StateNodes 00032 * - '<tt>spider </tt><i>name</i>' - spider the current structure of StateNode named <i>name</i> 00033 * - '<tt>listen </tt><i>name</i>' - send updates regarding the activation status of <i>name</i> and its subnodes; you can specify a state which is not yet running 00034 * - '<tt>ignore </tt><i>name</i>' - cancels a previous listen command 00035 * - '<tt>clear</tt>' - cancels all previous listen commands; should be called at the beginning or end of each connection, preferably both 00036 * 00037 * Each of those commands should be terminated with a newline - 00038 * i.e. one command per line 00039 * 00040 * After a <tt>list</tt> command, the first line will be the number 00041 * of StateNodes, followed by that number of lines, one StateNode 00042 * name per line. 00043 * 00044 * After a <tt>spider</tt> command, an XML description of the model 00045 * will be sent. If no matching StateNode is found, an warning will 00046 * be displayed on #serr, and an empty model 00047 * ("<model></model>") returned over the network 00048 * connection. 00049 * 00050 * All other commands give no direct response - listen can be 00051 * executed before the specified StateNode is yet running, and ignore 00052 * doesn't care whether or not the specified StateNode was actually 00053 * being listened for. 00054 * 00055 * The format of the model is: 00056 @verbatim 00057 <!DOCTYPE model [ 00058 <!ELEMENT model (state*, transition*)> 00059 <!ELEMENT state (state*, transition*)> 00060 <!ELEMENT transition (source+, dest+)> 00061 <!ELEMENT source (#PCDATA)> 00062 <!ELEMENT dest (#PCDATA)> 00063 00064 <!ATTLIST state id CDATA #REQUIRED> 00065 <!ATTLIST state class CDATA #REQUIRED> 00066 <!ATTLIST transition id CDATA #REQUIRED> 00067 <!ATTLIST transition class CDATA #REQUIRED> 00068 ]>@endverbatim 00069 * 00070 * The format of status updates following a listen command is: 00071 @verbatim 00072 <!DOCTYPE event [ 00073 <!ELEMENT event (fire*, statestart*, statestop*)> 00074 <!ELEMENT fire (EMPTY)> 00075 <!ELEMENT statestart (EMPTY)> 00076 <!ELEMENT statestop (EMPTY)> 00077 00078 <!ATTLIST fire id CDATA #REQUIRED> 00079 <!ATTLIST fire time CDATA #REQUIRED> 00080 <!ATTLIST statestart id CDATA #REQUIRED> 00081 <!ATTLIST statestart time CDATA #REQUIRED> 00082 <!ATTLIST statestop id CDATA #REQUIRED> 00083 <!ATTLIST statestop time CDATA #REQUIRED> 00084 ]>@endverbatim 00085 * 00086 * The 'event' node is also used for the results of logImage(), logMessage(), and logWebcam(). 00087 */ 00088 class EventLogger : public ControlBase, public EventListener { 00089 public: 00090 //!constructor 00091 EventLogger(); 00092 //!destructor 00093 virtual ~EventLogger(); 00094 00095 //!opens a custom (embedded) menu to toggle individual EGIDs 00096 virtual ControlBase* doSelect(); 00097 00098 virtual void refresh(); 00099 00100 //!sends all events received to stdout and/or logfile 00101 virtual void processEvent(const EventBase& event); 00102 00103 //!returns #logSocket 00104 static class Socket* getLogSocket() { return logSocket; } 00105 00106 //! returns #port 00107 static int getLogSocketPort() { return port; } 00108 00109 //! sets #port 00110 static void setLogSocketPort(int p) { port=p; } 00111 00112 //! send the current camera image over the log socket 00113 static void logImage(FilterBankGenerator& fbg, unsigned int layer, unsigned int channel, const BehaviorBase* source=NULL); 00114 00115 //! send a string over the log socket 00116 static void logMessage(std::string msg, const BehaviorBase* source=NULL, const char* icon=NULL, unsigned int placement=0); 00117 00118 //! request that the desktop side take a picture with the webcam (if available) 00119 static void logWebcam(const BehaviorBase* source=NULL); 00120 00121 static int callback(char *buf, int bytes); //!< called by wireless when there's new data 00122 00123 protected: 00124 static EventLogger * theOne; //!< the instance which will handle network communication 00125 00126 //! a separate processEvent to distinguish between events requested for logging and events requested by a remote monitor 00127 class StateMachineListener : public EventListener { 00128 //! forwards any events received to EventLogger::theOne's EventLogger::processStateMachineEvent() 00129 /*! EventLogger::runCommand() is responsible for maintaining which events this is listening to */ 00130 virtual void processEvent(const EventBase& event) { 00131 EventLogger::theOne->processStateMachineEvent(event); 00132 } 00133 }; 00134 static class StateMachineListener smProcess; //!< handles state machine transitions if the Storyboard GUI (or other remote monitor) is listening for state machine events 00135 00136 virtual void clearSlots(); 00137 00138 //!sets the status char of slot @a i to @a c 00139 void setStatus(unsigned int i, char c); 00140 00141 //!checks to see if logfilePath differs from the StringInputControl's value and switches it if it is 00142 void checkLogFile(); 00143 00144 //! dumps all of the transitions and subnodes of a given statenode 00145 /*! if parent is NULL, will dump the results over #logSocket, otherwise adds the xml tree as a child of @a parent */ 00146 void spider(const StateNode* n, xmlNode* parent=NULL); 00147 00148 //! returns true iff @a n or one of its parents is found in #listen 00149 bool isListening(const StateNode* n); 00150 00151 //! parses commands sent from callback() 00152 void runCommand(const std::string& s); 00153 00154 //!just to prettify the data sent out - probably should make this a null-op to save bandwidth after debugging is done 00155 void indent(unsigned int level); 00156 00157 //!searches currently instantiated StateNodes to find the one named @a name 00158 const StateNode * find(const std::string& name); 00159 00160 //!if there is a remote monitor listening for state machine transitions, this will send them over 00161 /*!this is called by the StateMachineListener, which is subscribed to only 00162 * those machines which have been requested by the remote monitor */ 00163 virtual void processStateMachineEvent(const EventBase& event); 00164 00165 //! dumps elements of #queuedEvents over #logSocket, popping and freeing as it goes 00166 static void dumpQueuedEvents(); 00167 00168 //! writes an xmlNode out over #logSocket, freeing @a node when complete 00169 /*! uses @a doc if provided, otherwise makes a new temporary one which is then deleted again before the function returns */ 00170 static void dumpNode(xmlNode* node, xmlDoc* doc=NULL); 00171 00172 //!address of the logfile, if any (empty string is no logfile) 00173 std::string logfilePath; 00174 00175 //!if a filename is given, events are logged to here 00176 std::ofstream logfile; 00177 00178 //! events which are logged will be sent over this port in an xml format. See eventlog.dtd in the docs directory 00179 static class Socket* logSocket; 00180 00181 //! port number #logSocket will listen on 00182 static int port; 00183 00184 //! reference count for #logSocket -- when this hits 0, close the socket 00185 static unsigned int logSocketRefCount; 00186 00187 //!controls the level of verbosity - currently 0 through 2 00188 unsigned int verbosity; 00189 00190 typedef std::set<BehaviorBase*> registry_t; //!< the type of the behavior registry (BehaviorBase::registry) 00191 00192 typedef std::set<std::string> listen_t; //!< the type of #listen 00193 listen_t listen; //!< a set of state machine names which should have their subnodes monitored 00194 00195 typedef std::queue<xmlNode*> queuedEvents_t; //!< the type of #queuedEvents 00196 static queuedEvents_t queuedEvents; //!< if logImage/logMessage/etc. are called during a transition, need to queue them until the transition event is complete 00197 00198 typedef std::stack<xmlNode*> transStack_t; //!< the type of #transStack 00199 static transStack_t transStack; //!< if another transition occurs during the processing of another, have to recurse on processing the new transition first 00200 }; 00201 00202 /*! @file 00203 * @brief Describes EventLogger, which allows logging of events to the console or a file 00204 * @author ejt (Creator) 00205 */ 00206 00207 #endif |
Tekkotsu v5.1CVS |
Generated Mon May 9 04:58:38 2016 by Doxygen 1.6.3 |