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