00001 #include "EventLogger.h"
00002 #include "Events/EventRouter.h"
00003 #include "Motion/MMAccessor.h"
00004 #ifdef TGT_HAS_LEDS
00005 # include "Motion/LedMC.h"
00006 #endif
00007 #include "ValueEditControl.h"
00008 #include "StringInputControl.h"
00009 #include "NullControl.h"
00010 #include <sstream>
00011 #include "Sound/SoundManager.h"
00012 #include "Vision/FilterBankGenerator.h"
00013 #include "Vision/JPEGGenerator.h"
00014 #include "Shared/Base64.h"
00015 #include "Behaviors/StateNode.h"
00016 #include "Behaviors/Transition.h"
00017 #include "Shared/Config.h"
00018 #include "Shared/debuget.h"
00019
00020 #include <libxml/xmlmemory.h>
00021 #include <libxml/parser.h>
00022
00023 Socket* EventLogger::logSocket=NULL;
00024 unsigned int EventLogger::logSocketRefCount=0;
00025 int EventLogger::port=10080;
00026 EventLogger * EventLogger::theOne=NULL;
00027 EventLogger::queuedEvents_t EventLogger::queuedEvents;
00028 EventLogger::transStack_t EventLogger::transStack;
00029
00030 EventLogger::StateMachineListener EventLogger::smProcess;
00031
00032 EventLogger::EventLogger()
00033 : ControlBase("Event Logger","Allows you to see/log all of the un-trapped events as they are generated"),
00034 logfilePath(), logfile(), verbosity(0), listen() {
00035 for(unsigned int i=0; i<EventBase::numEGIDs; i++) {
00036 std::string tmp=EventBase::EventGeneratorNames[i];
00037 pushSlot(new NullControl(("[ ] "+tmp).c_str(),"Show/hide events from "+tmp));
00038 }
00039 pushSlot(NULL);
00040 pushSlot(new ValueEditControl<unsigned int>("Verbosity","Controls verbosity level: 0=(gen,source,type); 1=0+gen_id,source_id,type_id; 2=1+duration,timestamp; 3=2+magnitude; additional columns may be added for subclass info","Please enter a new verbosity level: 0=(gen,source,type); 1=0+gen_id,source_id,type_id; 2=1+duration,timestamp; 3=2+magnitude; additional columns may be added for subclass info",&verbosity));
00041 pushSlot(new ControlBase("[X] Console Output","If selected, outputs events to the console"));
00042 pushSlot(new StringInputControl("[ ] File Output","Please enter the filename to log to (in /ms/...)"));
00043 if(logSocket==NULL) {
00044 theOne=this;
00045 ASSERT(logSocketRefCount==0,"logSocket is NULL, ref count is non-zero");
00046 logSocket=wireless->socket(Socket::SOCK_STREAM,1024,1<<15);
00047 wireless->setDaemon(logSocket);
00048 wireless->setReceiver(logSocket, callback);
00049 wireless->listen(logSocket,port);
00050 }
00051 logSocketRefCount++;
00052 }
00053
00054 EventLogger::~EventLogger() {
00055 while(!queuedEvents.empty())
00056 queuedEvents.pop();
00057 clearSlots();
00058 if(--logSocketRefCount==0) {
00059 wireless->setDaemon(logSocket,false);
00060 wireless->close(logSocket);
00061 logSocket=NULL;
00062 }
00063 if(theOne==this)
00064 theOne=NULL;
00065 }
00066
00067 ControlBase* EventLogger::doSelect() {
00068 ControlBase* ans=this;
00069 for(unsigned int i=0; i<hilights.size(); i++) {
00070 unsigned int cur=hilights[i];
00071 if(cur<EventBase::numEGIDs) {
00072 if(options[cur]->getName()[1]!=' ') {
00073 erouter->removeListener(this,(EventBase::EventGeneratorID_t)(cur));
00074 setStatus(cur,' ');
00075 } else {
00076 erouter->addListener(this,(EventBase::EventGeneratorID_t)(cur));
00077 setStatus(cur,'X');
00078 }
00079 } else if(cur==EventBase::numEGIDs+1) {
00080 ans=options[cur];
00081 } else if(cur==EventBase::numEGIDs+2) {
00082 if(options[cur]->getName()[1]!=' ') {
00083 setStatus(cur,' ');
00084 } else {
00085 setStatus(cur,'X');
00086 }
00087 } else if(cur==EventBase::numEGIDs+3) {
00088 if(options[cur]->getName()[1]!=' ') {
00089 logfile.close();
00090 options[cur]->setName("[ ] File Output");
00091 } else {
00092 ans=options[cur];
00093 }
00094 }
00095 sndman->playFile(config->controller.select_snd);
00096 }
00097 if(ans==this)
00098 refresh();
00099 return ans;
00100 }
00101
00102 void EventLogger::refresh() {
00103 checkLogFile();
00104 ControlBase::refresh();
00105 }
00106
00107
00108 void EventLogger::processEvent(const EventBase& event) {
00109 std::string logdata = event.getDescription(true,verbosity);
00110 if(options[EventBase::numEGIDs+2]->getName()[1]=='X')
00111 sout->printf("EVENT: %s\n",logdata.c_str());
00112 if(logSocket!=NULL && wireless->isConnected(logSocket->sock)) {
00113 xmlNode * cur = xmlNewNode(NULL,(const xmlChar*)"");
00114 xmlSetProp(cur,(const xmlChar*)"type",(const xmlChar*)"log");
00115 xmlNode * desc = xmlNewNode(NULL,(const xmlChar*)"param");
00116 event.saveXML(cur);
00117 xmlAddChild(cur,desc);
00118 xmlSetProp(desc,(const xmlChar*)"name",(const xmlChar*)"description");
00119 xmlSetProp(desc,(const xmlChar*)"value",(const xmlChar*)event.getDescription(true,3).c_str());
00120 xmlBuffer* buf=xmlBufferCreate();
00121 xmlDoc * doc = xmlNewDoc((const xmlChar*)"1.0");
00122 int n=xmlNodeDump(buf,doc,cur,0,1);
00123 xmlFreeNode(cur);
00124 xmlFreeDoc(doc);
00125 byte * nbuf = logSocket->getWriteBuffer(n+1);
00126 if(nbuf!=NULL) {
00127 memcpy(nbuf,xmlBufferContent(buf),n);
00128 nbuf[n]='\n';
00129 logSocket->write(n+1);
00130 }
00131 xmlBufferFree(buf);
00132 }
00133 checkLogFile();
00134 if(logfile)
00135 logfile << logdata << std::endl;
00136 }
00137
00138 void EventLogger::logImage(FilterBankGenerator& fbg, unsigned int layer, unsigned int channel, const BehaviorBase* source) {
00139 if(logSocket==NULL || !wireless->isConnected(logSocket->sock))
00140 return;
00141
00142 char * binbuf;
00143 unsigned int len;
00144 if(JPEGGenerator* jpeg=dynamic_cast<JPEGGenerator*>(&fbg)) {
00145 binbuf=(char*)jpeg->getImage(layer,channel);
00146 len=jpeg->getImageSize(layer,channel);
00147 } else {
00148 fbg.selectSaveImage(layer,channel);
00149 len=fbg.getBinSize();
00150 binbuf=new char[len];
00151 fbg.saveBuffer(binbuf,len);
00152 }
00153 std::string b64buf=base64::encode(binbuf,len);
00154 if(binbuf!=(char*)fbg.getImage(layer,channel))
00155 delete [] binbuf;
00156
00157 xmlNode * cur = xmlNewNode(NULL,(const xmlChar*)"event");
00158 xmlSetProp(cur,(const xmlChar*)"type",(const xmlChar*)"image");
00159 if(source!=NULL)
00160 xmlSetProp(cur,(const xmlChar*)"sid",(const xmlChar*)source->getName().c_str());
00161 char timebuf[20];
00162 snprintf(timebuf,20,"%d",get_time());
00163 xmlSetProp(cur,(const xmlChar*)"time",(const xmlChar*)timebuf);
00164 xmlNewChild(cur,NULL,(const xmlChar*)"image",(const xmlChar*)b64buf.c_str());
00165 queuedEvents.push(cur);
00166 if(transStack.empty())
00167 dumpQueuedEvents();
00168 }
00169
00170 void EventLogger::logMessage(std::string msg, const BehaviorBase* source, const char* icon, unsigned int placement) {
00171 if(logSocket==NULL || !wireless->isConnected(logSocket->sock))
00172 return;
00173
00174 xmlNode * cur = xmlNewNode(NULL,(const xmlChar*)"event");
00175 xmlSetProp(cur,(const xmlChar*)"type",(const xmlChar*)"userlog");
00176 if(source!=NULL)
00177 xmlSetProp(cur,(const xmlChar*)"sid",(const xmlChar*)source->getName().c_str());
00178 if(icon!=NULL)
00179 xmlSetProp(cur,(const xmlChar*)"icon",(const xmlChar*)icon);
00180 const unsigned int len=20;
00181 char sbuf[len];
00182 snprintf(sbuf,len,"%d",placement);
00183 xmlSetProp(cur,(const xmlChar*)"voff",(const xmlChar*)sbuf);
00184 snprintf(sbuf,len,"%d",get_time());
00185 xmlSetProp(cur,(const xmlChar*)"time",(const xmlChar*)sbuf);
00186 xmlNodeSetContent(cur,(const xmlChar*)msg.c_str());
00187 queuedEvents.push(cur);
00188 if(transStack.empty())
00189 dumpQueuedEvents();
00190 }
00191
00192 void EventLogger::logWebcam(const BehaviorBase* source) {
00193 if(logSocket==NULL || !wireless->isConnected(logSocket->sock))
00194 return;
00195
00196 xmlNode * cur = xmlNewNode(NULL,(const xmlChar*)"event");
00197 xmlSetProp(cur,(const xmlChar*)"type",(const xmlChar*)"webcam");
00198 if(source!=NULL)
00199 xmlSetProp(cur,(const xmlChar*)"sid",(const xmlChar*)source->getName().c_str());
00200 const unsigned int len=20;
00201 char sbuf[len];
00202 snprintf(sbuf,len,"%d",get_time());
00203 xmlSetProp(cur,(const xmlChar*)"time",(const xmlChar*)sbuf);
00204 xmlNodeSetContent(cur,(const xmlChar*)" ");
00205 queuedEvents.push(cur);
00206 if(transStack.empty())
00207 dumpQueuedEvents();
00208 }
00209
00210 void EventLogger::clearSlots() {
00211 erouter->removeListener(this);
00212 ControlBase::clearSlots();
00213 }
00214
00215 void EventLogger::setStatus(unsigned int i, char c) {
00216 std::string tmp=options[i]->getName();
00217 tmp[1]=c;
00218 options[i]->setName(tmp);
00219 }
00220
00221 void EventLogger::checkLogFile() {
00222 unsigned int cur=EventBase::numEGIDs+3;
00223 StringInputControl * strin=dynamic_cast<StringInputControl*>(options[cur]);
00224 ASSERTRET(strin!=NULL,"The StringInputControl is misplaced");
00225 if(strin->getLastInput()!=logfilePath) {
00226 logfile.close();
00227 logfilePath=strin->getLastInput();
00228 logfile.clear();
00229 if(logfilePath.size()!=0) {
00230 sout->printf("Opening `%s'\n",(config->portPath(logfilePath)).c_str());
00231 logfile.open((config->portPath(logfilePath)).c_str());
00232 if(!logfile.fail()) {
00233 setStatus(cur,'X');
00234 strin->setName(strin->getName()+": "+logfilePath);
00235 } else {
00236 serr->printf("Opening `%s' failed\n",(config->portPath(logfilePath)).c_str());
00237 }
00238 }
00239 }
00240 }
00241
00242
00243 void EventLogger::spider(const StateNode* n, xmlNode* parent) {
00244 if(n==NULL)
00245 return;
00246
00247 xmlNode * cur = xmlNewNode(NULL,(const xmlChar*)"state");
00248 ASSERTRET(cur!=NULL,"EventLogger::spider() could not allocate new xml state node");
00249 xmlSetProp(cur,(const xmlChar*)"class",(const xmlChar*)n->getClassName().c_str());
00250 xmlSetProp(cur,(const xmlChar*)"id",(const xmlChar*)n->getName().c_str());
00251
00252 const std::vector<StateNode*>& subnodes=n->getNodes();
00253 if(subnodes.size()>0) {
00254
00255
00256 std::set<const Transition*> transitions;
00257
00258 for(unsigned int i=0; i<subnodes.size(); i++) {
00259 spider(subnodes[i],cur);
00260 const std::vector<Transition*>& curt=subnodes[i]->getTransitions();
00261 transitions.insert(curt.begin(),curt.end());
00262 }
00263
00264
00265 for(std::set<const Transition*>::const_iterator it=transitions.begin(); it!=transitions.end(); it++) {
00266 xmlNode * t = xmlAddChild(cur,xmlNewNode(NULL,(const xmlChar*)"transition"));
00267 ASSERTRET(t!=NULL,"EventLogger::spider() could not allocate new xml transition node");
00268 xmlSetProp(t,(const xmlChar*)"class",(const xmlChar*)(*it)->getClassName().c_str());
00269 xmlSetProp(t,(const xmlChar*)"id",(const xmlChar*)(*it)->getName().c_str());
00270
00271 typedef std::vector<StateNode*> statevec_t;
00272 const statevec_t& incoming=(*it)->getSources();
00273 for(statevec_t::const_iterator nit=incoming.begin(); nit!=incoming.end(); ++nit) {
00274 xmlNode * sn = xmlAddChild(t,xmlNewNode(NULL,(const xmlChar*)"source"));
00275 ASSERTRET(sn!=NULL,"EventLogger::spider() could not allocate new xml transition source node");
00276 xmlNodeSetContent(sn,(const xmlChar*)(*nit)->getName().c_str());
00277 }
00278 const statevec_t& outgoing=(*it)->getDestinations();
00279 for(statevec_t::const_iterator nit=outgoing.begin(); nit!=outgoing.end(); ++nit) {
00280 xmlNode * sn = xmlAddChild(t,xmlNewNode(NULL,(const xmlChar*)"destination"));
00281 ASSERTRET(sn!=NULL,"EventLogger::spider() could not allocate new xml transition source node");
00282 xmlNodeSetContent(sn,(const xmlChar*)(*nit)->getName().c_str());
00283 }
00284 }
00285 }
00286 if(parent==NULL)
00287 dumpNode(cur);
00288 else
00289 xmlAddChild(parent,cur);
00290 }
00291
00292 bool EventLogger::isListening(const StateNode* n) {
00293 while(n!=NULL) {
00294 if(listen.find(n->getName())!=listen.end())
00295 return true;
00296 n=n->getParent();
00297 }
00298 return false;
00299 }
00300
00301 void EventLogger::indent(unsigned int level) {
00302 for(unsigned int i=0; i<level; i++)
00303 logSocket->printf(" ");
00304 }
00305
00306 const StateNode * EventLogger::find(const std::string& sname) {
00307 const registry_t& registry=BehaviorBase::getRegistry();
00308 for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00309 const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00310 if(cur!=NULL && cur->getName()==sname)
00311 return cur;
00312 }
00313
00314 return NULL;
00315 }
00316
00317 void EventLogger::runCommand(const std::string& s) {
00318 if(s==std::string("list")) {
00319 const registry_t& registry=BehaviorBase::getRegistry();
00320 unsigned int numstate=0;
00321 for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00322 const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00323 if(cur!=NULL)
00324 numstate++;
00325 }
00326 logSocket->printf("%d\n",numstate);
00327 for(registry_t::const_iterator it=registry.begin(); it!=registry.end(); it++) {
00328 const StateNode * cur=dynamic_cast<const StateNode*>(*it);
00329 if(cur!=NULL)
00330 logSocket->printf("%s\n",cur->getName().c_str());
00331 }
00332
00333 } else if(s.find("spider ")==0) {
00334 const StateNode * n=find(s.substr(7));
00335 if(n==NULL) {
00336 serr->printf("WARNING: EventLogger could not find \"%s\" for spidering\n",s.substr(7).c_str());
00337 logSocket->printf("<model></model>\n");
00338 } else {
00339 logSocket->printf("<model>\n");
00340 spider(n);
00341 logSocket->printf("</model>\n");
00342 }
00343
00344 } else if(s.find("listen ")==0) {
00345 if(listen.size()==0) {
00346 erouter->addListener(&smProcess,EventBase::stateMachineEGID);
00347 erouter->addListener(&smProcess,EventBase::stateTransitionEGID);
00348 }
00349 listen.insert(s.substr(7));
00350
00351 } else if(s.find("ignore ")==0) {
00352 listen.erase(s.substr(7));
00353 if(listen.size()==0)
00354 erouter->removeListener(&smProcess);
00355
00356 } else if(s=="clear") {
00357 listen.clear();
00358 erouter->removeListener(&smProcess);
00359
00360 } else {
00361 serr->printf("EventLogger::runCommand() - bad message: '%s'\n",s.c_str());
00362 }
00363 }
00364
00365
00366 int EventLogger::callback(char *buf, int bytes) {
00367 if(EventLogger::theOne==NULL)
00368 return 0;
00369 static std::string cmd;
00370 for(int i=0; i<bytes; i++) {
00371 if(buf[i]=='\n') {
00372 EventLogger::theOne->runCommand(cmd);
00373 cmd.clear();
00374 } else if(buf[i]!='\r')
00375 cmd+=buf[i];
00376 }
00377 return 0;
00378 }
00379
00380 void EventLogger::processStateMachineEvent(const EventBase& e) {
00381 if(!wireless->isConnected(logSocket->sock) || listen.size()==0)
00382 return;
00383
00384 if(e.getGeneratorID()==EventBase::stateTransitionEGID) {
00385 bool care=false;
00386 const Transition * trans = reinterpret_cast<Transition*>(e.getSourceID());
00387 const std::vector<StateNode*>& incoming=trans->getSources();
00388 const std::vector<StateNode*>& outgoing=trans->getDestinations();
00389 for(std::vector<StateNode*>::const_iterator it=incoming.begin(); it!=incoming.end() && !care; it++)
00390 care=isListening(*it);
00391 for(std::vector<StateNode*>::const_iterator it=outgoing.begin(); it!=outgoing.end() && !care; it++)
00392 care=isListening(*it);
00393 if(!care)
00394 return;
00395
00396 if(e.getTypeID()==EventBase::activateETID) {
00397 xmlNode * root = xmlNewNode(NULL,(const xmlChar*)"event");
00398 xmlNode * fire = xmlAddChild(root,xmlNewNode(NULL,(const xmlChar*)"fire"));
00399 xmlSetProp(fire,(const xmlChar*)"id",(const xmlChar*)trans->getName().c_str());
00400 const unsigned int len=20;
00401 char sbuf[len];
00402 snprintf(sbuf,len,"%d",e.getTimeStamp());
00403 xmlSetProp(fire,(const xmlChar*)"time",(const xmlChar*)sbuf);
00404 transStack.push(root);
00405 queuedEvents.push(root);
00406 } else {
00407 ASSERTRET(!transStack.empty(),"got a transition deactivate that I should care about, but I didn't see the activate");
00408 transStack.pop();
00409 if(transStack.empty())
00410 dumpQueuedEvents();
00411 }
00412
00413 } else if(e.getGeneratorID()==EventBase::stateMachineEGID) {
00414 if(e.getTypeID()==EventBase::statusETID)
00415 return;
00416 const StateNode * beh=reinterpret_cast<StateNode*>(e.getSourceID());
00417 if(!isListening(beh))
00418 return;
00419 if(e.getTypeID()!=EventBase::activateETID && e.getTypeID()!=EventBase::deactivateETID) {
00420 serr->printf("WARNING: Unrecognized TypeID %d\n",e.getTypeID());
00421 return;
00422 }
00423
00424 xmlNode * root = transStack.empty() ? xmlNewNode(NULL,(const xmlChar*)"event") : transStack.top();
00425 const char* sttypestr = (e.getTypeID()==EventBase::activateETID) ? "statestart" : "statestop";
00426 xmlNode * st = xmlAddChild(root,xmlNewNode(NULL,(const xmlChar*)sttypestr));
00427 xmlSetProp(st,(const xmlChar*)"id",(const xmlChar*)beh->getName().c_str());
00428 const unsigned int len=20;
00429 char sbuf[len];
00430 snprintf(sbuf,len,"%d",e.getTimeStamp());
00431 xmlSetProp(st,(const xmlChar*)"time",(const xmlChar*)sbuf);
00432
00433 if(transStack.empty()) {
00434 queuedEvents.push(root);
00435 dumpQueuedEvents();
00436 }
00437
00438 } else {
00439 serr->printf("WARNING: Unknown event %s (%s)\n",e.getName().c_str(),e.getDescription().c_str());
00440 }
00441 }
00442
00443 void EventLogger::dumpQueuedEvents() {
00444 xmlDoc * doc = xmlNewDoc((const xmlChar*)"1.0");
00445 while(!queuedEvents.empty()) {
00446 dumpNode(queuedEvents.front(),doc);
00447 queuedEvents.pop();
00448 }
00449 xmlFreeDoc(doc);
00450 }
00451
00452 void EventLogger::dumpNode(xmlNode* node, xmlDoc* doc) {
00453 xmlBuffer* buf=xmlBufferCreate();
00454 int n=xmlNodeDump(buf,doc,node,0,1);
00455 byte * nbuf = logSocket->getWriteBuffer(n+1);
00456 if(nbuf!=NULL) {
00457 memcpy(nbuf,xmlBufferContent(buf),n);
00458 nbuf[n]='\n';
00459 logSocket->write(n+1);
00460 }
00461 xmlBufferFree(buf);
00462 xmlFreeNode(node);
00463 }
00464
00465
00466
00467
00468
00469
00470
00471