Homepage Demos Overview Downloads Tutorials Reference
Credits

SpiderMachineBehavior.cc

Go to the documentation of this file.
00001 #include "SpiderMachineBehavior.h"
00002 #include "Events/EventRouter.h"
00003 #include "Behaviors/StateNode.h"
00004 #include "Wireless/Wireless.h"
00005 
00006 SpiderMachineBehavior * SpiderMachineBehavior::theOne=NULL;
00007 unsigned int SpiderMachineBehavior::port=10080;
00008 
00009 void SpiderMachineBehavior::DoStart() {
00010   BehaviorBase::DoStart(); // do this first
00011   theOne=this;
00012   // Turn on wireless
00013   cmdsock=wireless->socket(SocketNS::SOCK_STREAM, 1024, 1024*10);
00014   wireless->setDaemon(cmdsock,true);
00015   wireless->setReceiver(cmdsock->sock, callback);
00016   wireless->listen(cmdsock->sock, port);
00017   erouter->addListener(this,EventBase::stateMachineEGID);
00018   erouter->addListener(this,EventBase::stateTransitionEGID);
00019 }
00020 
00021 void SpiderMachineBehavior::DoStop() {
00022   erouter->removeListener(this);
00023   expected.clear();
00024   while(!queuedEvents.empty())
00025     queuedEvents.pop();
00026   // Close socket; turn wireless off
00027   wireless->setDaemon(cmdsock,false);
00028   wireless->close(cmdsock);
00029   if(theOne==this)
00030     theOne=NULL;
00031   BehaviorBase::DoStop(); // do this last
00032 }
00033 
00034 void SpiderMachineBehavior::processEvent(const EventBase& e) {
00035   if(!wireless->isConnected(cmdsock->sock) || listen.size()==0)
00036     return;
00037 
00038   if(e.getGeneratorID()==EventBase::stateTransitionEGID) {
00039     bool care=false;
00040     const Transition * trans = reinterpret_cast<Transition*>(e.getSourceID());
00041     const std::vector<StateNode*>& incoming=trans->getSources();
00042     const std::vector<StateNode*>& outgoing=trans->getDestinations();
00043     for(std::vector<StateNode*>::const_iterator it=incoming.begin(); it!=incoming.end() && !care; it++)
00044       care=isListening(*it);
00045     for(std::vector<StateNode*>::const_iterator it=outgoing.begin(); it!=outgoing.end() && !care; it++)
00046       care=isListening(*it);
00047     if(!care)
00048       return;
00049 
00050     if(expected.size()!=0) {
00051       queuedEvents.push(e);
00052     } else {
00053       cmdsock->printf("<event>\n");
00054       indent(1);
00055       cmdsock->printf("<fire id=\"%s\" time=\"%d\" />\n",trans->getName().c_str(),e.getTimeStamp());
00056       expected.insert(incoming.begin(),incoming.end());
00057       expected.insert(outgoing.begin(),outgoing.end());
00058       while(queuedEvents.size()>0) {
00059         EventBase qe=queuedEvents.front();
00060         queuedEvents.pop();
00061         processEvent(qe);
00062       }
00063     }
00064 
00065   } else if(e.getGeneratorID()==EventBase::stateMachineEGID) {
00066     if(e.getTypeID()==EventBase::statusETID)
00067       return;
00068     const StateNode * beh=reinterpret_cast<StateNode*>(e.getSourceID());
00069     expected_t::iterator it=expected.find(beh);
00070     char * format;
00071     if(isListening(beh)) {
00072       if(it==expected.end()) { //if not found
00073         if(queuedEvents.size()==0)
00074           format="<event><state%s id=\"%s\" time=\"%d\" /></event>\n"; // unexpected
00075         else {
00076           queuedEvents.push(e);
00077           return;
00078         }
00079       } else
00080         format="  <state%s id=\"%s\" time=\"%d\" />\n"; // expected as part of transition
00081       if(e.getTypeID()==EventBase::activateETID)
00082         cmdsock->printf(format,"start",beh->getName().c_str(),e.getTimeStamp());
00083       else if(e.getTypeID()==EventBase::deactivateETID)
00084         cmdsock->printf(format,"stop",beh->getName().c_str(),e.getTimeStamp());
00085       else
00086         serr->printf("WARNING: Unrecognized TypeID %d\n",e.getTypeID());
00087     }
00088     if(it!=expected.end()) { //was found
00089       expected.erase(it);
00090       if(expected.size()==0) {
00091         cmdsock->printf("</event>\n");
00092         while(queuedEvents.size()>0) {
00093           EventBase qe=queuedEvents.front();
00094           queuedEvents.pop();
00095           processEvent(qe);
00096         }
00097       }
00098     }
00099 
00100   } else {
00101     serr->printf("WARNING: Unknown event %s (%s)\n",e.getName().c_str(),e.getDescription().c_str());
00102   }
00103 }
00104 
00105 void SpiderMachineBehavior::spider(const StateNode* n, unsigned int depth/*=0*/) {
00106   if(n==NULL)
00107     return;
00108 
00109   const std::vector<StateNode*>& subnodes=n->getNodes();
00110   if(subnodes.size()==0) {
00111     // it's a leaf node, no subnodes or transitions between them
00112     indent(depth);
00113     cmdsock->printf("<state class=\"%s\" id=\"%s\" />\n", n->getClassName().c_str(), n->getName().c_str());
00114   } else {
00115 
00116     // first output current node's info
00117     indent(depth);
00118     cmdsock->printf("<state class=\"%s\" id=\"%s\">\n", n->getClassName().c_str(), n->getName().c_str());
00119 
00120     std::set<const Transition*> transitions;
00121     // now recurse on sub-nodes, extracting all of the subnodes transitions
00122     for(unsigned int i=0; i<subnodes.size(); i++) {
00123       spider(subnodes[i],depth+1);
00124       const std::vector<Transition*>& curt=subnodes[i]->getTransitions();
00125       transitions.insert(curt.begin(),curt.end());
00126     }
00127 
00128     // now output transitions between subnodes we collected in previous step
00129     for(std::set<const Transition*>::const_iterator it=transitions.begin(); it!=transitions.end(); it++) {
00130       indent(depth+1);
00131       cmdsock->printf("<transition class=\"%s\" id=\"%s\">\n", (*it)->getClassName().c_str(), (*it)->getName().c_str());
00132       const std::vector<StateNode*>& incoming=(*it)->getSources();
00133       for(unsigned int i=0; i<incoming.size(); i++) {
00134         indent(depth+2);
00135         cmdsock->printf("<source>%s</source>\n",incoming[i]->getName().c_str());
00136       }
00137       const std::vector<StateNode*>& outgoing=(*it)->getDestinations();
00138       for(unsigned int i=0; i<outgoing.size(); i++) {
00139         indent(depth+2);
00140         cmdsock->printf("<destination>%s</destination>\n",outgoing[i]->getName().c_str());
00141       }
00142       indent(depth+1);
00143       cmdsock->printf("</transition>\n");
00144     }
00145 
00146     indent(depth);
00147     cmdsock->printf("</state>\n");
00148   }
00149 }
00150   
00151 bool SpiderMachineBehavior::isListening(const StateNode* n) {
00152   while(n!=NULL) {
00153     if(listen.find(n->getName())!=listen.end())
00154       return true;
00155     n=n->getParent();
00156   }
00157   return false;
00158 }
00159 
00160 void SpiderMachineBehavior::indent(unsigned int level) {
00161   for(unsigned int i=0; i<level; i++)
00162     cmdsock->printf("  ");
00163 }
00164 
00165 const StateNode * SpiderMachineBehavior::find(const std::string& name) {
00166   for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00167     const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00168     if(cur!=NULL && cur->getName()==name)
00169       return cur;
00170   }
00171   //serr->printf("WARNING: SpiderMachineBehavior Could not find StateNode named `%s'\n",name.c_str());
00172   return NULL;
00173 }
00174 
00175 void SpiderMachineBehavior::runCommand(const std::string& s) {
00176   if(s==std::string("list")) {
00177     unsigned int numstate=0;
00178     for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00179       const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00180       if(cur!=NULL)
00181         numstate++;
00182     }
00183     cmdsock->printf("%d\n",numstate);
00184     for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00185       const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00186       if(cur!=NULL)
00187         cmdsock->printf("%s\n",cur->getName().c_str());
00188     }
00189 
00190   } else if(s.find("spider ")==0) {
00191     const StateNode * n=find(s.substr(7));
00192     if(n==NULL) {
00193       serr->printf("WARNING: SpiderMachineBehavior could not find \"%s\" for spidering\n",s.substr(7).c_str());
00194       cmdsock->printf("<model></model>\n");
00195     } else {
00196       cmdsock->printf("<model>\n");
00197       spider(n);
00198       cmdsock->printf("</model>\n");
00199     }
00200 
00201   } else if(s.find("listen ")==0) {
00202     listen.insert(s.substr(7));
00203 
00204   } else if(s.find("ignore ")==0) {
00205     listen.erase(s.substr(7));
00206 
00207   } else if(s=="clear") {
00208     listen.clear();
00209 
00210   } else {
00211     serr->printf("SpiderMachineBehavior::runCommand() - bad message: '%s'\n",s.c_str());
00212   }
00213 }
00214 
00215 // The command packet reassembly mechanism
00216 int SpiderMachineBehavior::callback(char *buf, int bytes) {
00217   if(SpiderMachineBehavior::theOne==NULL)
00218     return 0;
00219   static std::string cmd;
00220   for(int i=0; i<bytes; i++) {
00221     if(buf[i]=='\n') {
00222       SpiderMachineBehavior::theOne->runCommand(cmd);
00223       cmd.clear();
00224     } else if(buf[i]!='\r')
00225       cmd+=buf[i];
00226   }
00227   return 0;
00228 }
00229 
00230 /*! @file
00231  * @brief Implements SpiderMachineBehavior, which when active, active and connected over network socket, outputs structure of requested state machine(s)
00232  * @author ejt (Creator)
00233  *
00234  * $Author: ejt $
00235  * $Name: tekkotsu-2_2_2 $
00236  * $Revision: 1.3 $
00237  * $State: Exp $
00238  * $Date: 2004/12/17 20:18:54 $
00239  */

Tekkotsu v2.2.2
Generated Tue Jan 4 15:43:15 2005 by Doxygen 1.4.0