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

Tekkotsu v4.0
Generated Thu Nov 22 00:54:53 2007 by Doxygen 1.5.4