Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventLogger.h

Go 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