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