Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnSDUtils.cpp
- Committer:
- uci1
- Date:
- 2014-11-28
- Revision:
- 65:2cb3e99ce466
- Parent:
- 64:6c7a316eafad
- Child:
- 66:685f9d0a48ae
File content as of revision 65:2cb3e99ce466:
#include "SnSDUtils.h" #include "mbed.h" #include "SDFileSystem.h" #include "FATDirHandle.h" #include <string.h> #include <string> #include "SnConfigFrame.h" #include "SnEventFrame.h" #include "SnHeartbeatFrame.h" #include "SnClockSetFrame.h" #include "Watchdog.h" //#define DEBUG #define SUBDIRSEQ 100 // make a new subdir every X sequences const char* const SnSDUtils::kSDdir = "/sd"; const char* const SnSDUtils::kSDsubDir = "/sd/data"; const char* const SnSDUtils::kRunSeqListFilenm = "/sd/RunSeqLC.txt"; const uint16_t SnSDUtils::kMaxSeqNum = 64000; // max "normal" seq const uint16_t SnSDUtils::kBadSeqNum = 65000; // should be larger than kMaxSeqNum to separate "normal" and "bad" seqs char SnSDUtils::fgCurFileName[kFNBufSize]={0}; FILE* SnSDUtils::fgCurFile = 0; uint16_t SnSDUtils::fgCurSeq = 0; bool SnSDUtils::fgNeedToInit = true; const uint8_t SnSDUtils::kIOvers = 4; const uint32_t SnSDUtils::kMaxSizeOfFileHdr = sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t) +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1 SnSDUtils::InitSDFcn SnSDUtils::fgDoInit = 0; bool SnSDUtils::fgInitOk = false; static const uint16_t __kMaxUShort = ~0; bool SnSDUtils::InitSDCard(const bool force) { Watchdog::kick(); // don't reset if ((fgNeedToInit || force) && (fgDoInit!=0)) { fgInitOk = (*fgDoInit)() == 0; if (IsInitOk()) { fgNeedToInit = false; } } return fgInitOk; } const char* SnSDUtils::GetSubDirFor(const uint32_t run, const uint16_t seq, uint32_t& slen, const bool useSeq) { // returns a STATIC string! (so make a copy of it before use) // sets slen to the length of this string (same as strlen) Watchdog::kick(); // don't reset static const uint16_t tmplen = strlen(kSDsubDir)+50; static char* tmpsd = new char[tmplen]; slen = snprintf(tmpsd, tmplen, "%s/r%05ld", kSDsubDir, run); if (useSeq) { slen += snprintf(tmpsd+slen, tmplen-slen, "/s%05d", (seq/SUBDIRSEQ)*SUBDIRSEQ); } if (slen > tmplen) { slen = tmplen; } return tmpsd; } const char* SnSDUtils::GetOutFileName(const uint64_t macadr, const uint32_t run, const uint16_t seq) { // returns the formatted file name, or NULL if the directory is too long // and the full name cannot fit in the buffer // NOTE: this fcn uses a static buffer, and so should not be called // multiple times in the same line (that includes the calling of functions // that call this function!) // // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat // 35 chars 7 + 12 +1+ 5 +1+ 5 + 4 Watchdog::kick(); // don't reset uint32_t sdlen(0); std::string subdirs( GetSubDirFor(run, seq, sdlen, true) ); const char* subdir = subdirs.c_str(); if (sdlen<(kFNBufSize-37)) { static char tbuf[kFNBufSize]; memset(tbuf, 0, sizeof(char)*kFNBufSize); // if file name format changes, GetSeqNum must be changed too sprintf(tbuf, "%s/SnEvtsM%012llXr%05lds%05d.dat", subdir, macadr>>16, // 64 -> 48 bits run, seq); return tbuf; } else { return NULL; } } bool SnSDUtils::GetRunSeqFromFilename(const char* fn, uint32_t& run, uint16_t& seq) { Watchdog::kick(); // don't reset bool ret = false; const int32_t ncomp = strrchr(fn, 'r') - fn; #ifdef DEBUG printf("fn=%s, ncomp=%d\r\n",fn,ncomp); #endif if ((ncomp<strlen(fn)) && (ncomp>0)) { if (sscanf(fn+ncomp,"r%lus%hu.dat",&run,&seq)==2) { #ifdef DEBUG printf("run=%u, seq=%hu\r\n",run,seq); #endif ret = true; } } return ret; } /* uint16_t SnSDUtils::GetSeqNumFromFileName(const char* fn) { uint16_t seq=0; const uint32_t ncomp = strrchr(fn, 's') - fn; if (ncomp<strlen(fn)) { sscanf(fn+ncomp,"s%hu.dat",&seq); } return seq; } */ DIR* SnSDUtils::OpenOrMakeAllDirs(const char* dirname) { #ifdef DEBUG printf("OpenOrMakeAllDirs: [%s]\r\n",dirname); #endif Watchdog::kick(); // don't reset // try making the subdir DIR* sd(0); std::string dn(dirname); std::size_t slash(0); std::string sdr; bool ok=true; while (ok) { slash=dn.find_first_of('/',slash+1); if (slash==std::string::npos) { sdr = dn; // no more slashes ok=false; } else { sdr = dn.substr(0, slash); } #ifdef DEBUG printf("slash=%d, sdr=[%s] (%d), ok=%s\r\n", (int)slash, sdr.c_str(), (int)sdr.size(), ok ? "true" : "false"); #endif if (sd!=0) { // close the one from last time closedir(sd); } // skip the /sd, as it's not a real directory // should be skipped anyway, but.. if (sdr.compare(kSDdir)!=0) { #ifdef DEBUG printf("calling OpenOrMakeDir [%s]\r\n",sdr.c_str()); #endif sd = OpenOrMakeDir(sdr.c_str()); } } return sd; } DIR* SnSDUtils::OpenOrMakeDir(const char* dirname) { #ifdef DEBUG printf("open dir %s\r\n",dirname); #endif Watchdog::kick(); // don't reset if (InitSDCard()) { DIR* rd( opendir(dirname) ); if (rd==NULL) { // try making the directory #ifdef DEBUG printf("making dir %s\r\n",dirname); #endif mkdir(dirname, 0777); #ifdef DEBUG printf("opening dir %s\r\n",dirname); #endif rd = opendir(dirname); } #ifdef DEBUG printf("returning rd=%p\r\n",(void*)rd); #endif return rd; } else { return 0; } } uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr, const uint32_t run) { // count the files having expected filename format Watchdog::kick(); // don't reset uint16_t maxs(kBadSeqNum); if (InitSDCard()) { maxs = 0; // change back from kBadSeqNum! // get the run dir uint32_t rdlen(0); std::string rdnms ( GetSubDirFor(run, 0, rdlen, false) ); const char* rdnm = rdnms.c_str(); // open/make the run directory FATDirHandle* rd(static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) )); struct dirent* rdent; uint16_t dseq(0); #ifdef DEBUG printf("starting readdir loop over %p\r\n",(void*)rd); #endif while ( (rdent = readdir(rd))!=NULL ) { #ifdef DEBUG printf("rdent = %p\r\n",(void*)rdent); #endif if ((rd->filinfo()->fattrib & AM_DIR)!=0) { #ifdef DEBUG printf("is a dir\r\n"); #endif // is a directory const int ncm = sscanf(rdent->d_name, "s%hu", &dseq); if (ncm==1) { #ifdef DEBUG printf("dseq=%hu, maxs=%hu\r\n",dseq,maxs); #endif if ( (dseq>maxs) && (dseq<kMaxSeqNum) ) { maxs = dseq; } } } #ifdef DEBUG else { printf("not a dir\r\n"); } #endif } #ifdef DEBUG printf("closing directory %p\r\n",(void*)rd); #endif closedir(rd); #ifdef DEBUG printf("Found max seq dir num %hu for run %u\r\n",maxs,run); #endif Watchdog::kick(); // don't reset // open up the seq dir rdnms = GetSubDirFor(run, maxs, rdlen, true); rdnm = rdnms.c_str(); // runXseq0 filename (fn points to a static buffer) const char* fn = GetOutFileName(macadr, run, maxs) + rdlen + 1; // take out dir and '/'s // don't compare seq#. don't use num of chars in case seq is >999 const int32_t ncomp = strrchr(fn, 's') - fn; // open (or make) the run/seq dir rd = static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) ); // get the new sequence number (ok if it overflows this seq "bin") maxs=0; while ( (rdent = readdir(rd))!=NULL ) { Watchdog::kick(); // don't reset if ((rd->filinfo()->fattrib & AM_DIR)==0) { // is a file. // don't just count files, in case one seq was // transferred and erased in the middle of a run if (strncmp(rdent->d_name, fn, ncomp)==0) { // allow for deleted files to make gaps. // search for highest seq number and increase that if (sscanf((rdent->d_name)+ncomp,"s%hu.dat",&dseq)==1) { #ifdef DEBUG printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n", rdent->d_name, dseq, __kMaxUShort); #endif if (dseq==__kMaxUShort) { maxs = dseq; break; } #ifdef DEBUG printf("dseq=%hu, maxs=%hu\r\n",dseq,maxs); #endif if ( (dseq>=maxs) && (dseq<kMaxSeqNum)) { maxs=dseq+1; } if (maxs==__kMaxUShort) { break; } } } } } closedir(rd); } else { // no SD card } #ifdef DEBUG printf("return maxs=%hu\r\n",maxs); #endif return maxs; } FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent, const bool redoDir) { Watchdog::kick(); // don't reset FILE* f = 0; if (InitSDCard()) { //if ((name!=NULL) && ((*name)!=0) ) { // simple check if filename not set if (name!=NULL) { // simple check if filename not set #ifdef DEBUG printf("opening SD file. name=[%s]\r\n",name); #endif f = OpenSDFile(name, "rb", redoDir); /* if (setcurrent) { fgCurFile = f; strncpy(fgCurFileName, name, kFNBufSize-1); fgCurSeq = GetSeqNumFromFileName(fgCurFileName); } */ } } return f; } bool SnSDUtils::GetFullFilename(const char* name, std::string& ffn) { #ifdef DEBUG printf("GetFullFilename (%s)\r\n",name); #endif Watchdog::kick(); // don't reset bool ret = false; uint32_t run(0); uint16_t seq(0); const char* fn = strrchr(name, '/'); #ifdef DEBUG printf("w/o / : %s\r\n",fn); #endif if (fn!=NULL) { ++fn; // remove the / } else { fn = name; } ffn = ""; if (GetRunSeqFromFilename(fn, run, seq)) { #ifdef DEBUG printf("got run=%d, seq=%hu\r\n",run,seq); #endif uint32_t sdlen(0); std::string subds( GetSubDirFor(run,seq,sdlen, true) ); const char* subd = subds.c_str(); #ifdef DEBUG printf("subd=%s\r\n",subd); #endif ffn = subd; ffn += "/"; ret = true; } ffn += fn; #ifdef DEBUG printf("ffn=%s, ret=%d\r\n",ffn.c_str(),(int)ret); #endif return ret; } FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode, const bool redoDir) { // TODO: check if we have memory? #ifdef DEBUG printf("OpenSDFile: Trying to open %s.\r\n",name); #endif Watchdog::kick(); // don't reset FILE* f = 0; if (InitSDCard()) { std::string ffn; bool ok = true; #ifdef DEBUG printf("redoDir=%d\r\n",(int)redoDir); #endif if (redoDir) { #ifdef DEBUG printf("calling GetFullFilename\r\n"); #endif ok = GetFullFilename(name, ffn); #ifdef DEBUG printf("ffn=%s\r\n",ffn.c_str()); #endif } else { #ifdef DEBUG printf("looking for /\r\n"); #endif // make sure the directory exists const char* ld = strrchr(name, '/'); #ifdef DEBUG printf("ld=%p, ld-name = %d\r\n",ld,(int)(ld-name)); #endif if ((ld!=0) && (ld>name)) { std::string dn(name, ld-name); DIR* d = OpenOrMakeAllDirs(dn.c_str()); #ifdef DEBUG printf("d=%p\r\n",d); #endif if (d!=NULL) { closedir(d); } } // now just copy the (already-) full name ffn = name; } if ( ok && ffn.size()>0 ) { #ifdef DEBUG printf("OpenSDFile: %s, mode %s\r\n",ffn.c_str(),mode); #endif f = fopen(ffn.c_str(), mode); //setvbuf(f, 0, _IONBF, 0); // no buffering #ifdef DEBUG printf("OpenSDFile: f=%p\r\n",(void*)f); #endif } #ifdef DEBUG printf("ffn=%s\r\n",ffn.c_str()); #endif } return f; } FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr, const uint32_t run, const uint16_t minseq) { // opens a new file in the specified directory and writes this // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes) // #ifdef DEBUG printf("getting seq num for run %u, minseq %hu\r\n", run, minseq); #endif Watchdog::kick(); // don't reset fgCurFile = 0; fgCurSeq = GetSeqNum(macadr, run); #ifdef DEBUG printf("fgCurSeq=%hu\r\n",fgCurSeq); #endif if (InitSDCard()) { if (fgCurSeq<minseq) { fgCurSeq=minseq; } #ifdef DEBUG printf("getting output file name\r\n"); #endif memset(fgCurFileName, 0, sizeof(char)*kFNBufSize); strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1); //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq); #ifdef DEBUG printf("fgCurFileName=%s\r\n",fgCurFileName); #endif fgCurFile = 0; if (fgCurFileName!=NULL) { #ifdef DEBUG printf("opening SD file\r\n"); #endif fgCurFile = OpenSDFile(fgCurFileName, "wb", false); if (fgCurFile!=NULL && ferror(fgCurFile)==0) { #ifdef DEBUG printf("Writing file header\r\n"); #endif WriteFileHeader(fgCurFile, macadr, run, fgCurSeq); AddToRunSeqList(run, fgCurSeq); } } #ifdef DEBUG printf("fgCurFile=%p\r\n",(void*)fgCurFile); #endif } return fgCurFile; } void SnSDUtils::PrintFilesInDirs(const char* dirname) { Watchdog::kick(); // don't reset if (InitSDCard()) { DIR* d; struct dirent* dent; Watchdog::kick(); // don't reset if ( (d = opendir( dirname ))!=NULL ) { FATDirHandle* dir = static_cast<FATDirHandle*>(d); while ( (dent = readdir(d))!=NULL ) { printf("dn=%s. datr=%02x. dir=%d\r\n", dent->d_name, dir->filinfo()->fattrib, dir->filinfo()->fattrib & AM_DIR); if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) { std::string dnm(dirname); dnm += "/"; dnm += dent->d_name; PrintFilesInDirs(dnm.c_str()); } } closedir(d); } } } float SnSDUtils::GetFreeBytes() { Watchdog::kick(); // don't reset float frs(0); if (InitSDCard()) { FATFS* fs; DWORD fre_clust; f_getfree("0:",&fre_clust,&fs); frs = static_cast<float>(fs->csize) *static_cast<float>(fs->free_clust) #if _MAX_SS != 512 *(fs->ssize); #else *512; #endif #ifdef DEBUG printf("free space = %g b (%g GB, %g MB, %g KB)\r\n", frs, frs/1073741824.0, frs/1048576.0, frs/1024.0); #endif } return frs; } void SnSDUtils::GetDirProps(const char* dirname, uint32_t& nfiles, float& totbytes) { Watchdog::kick(); // don't reset nfiles = 0; totbytes = 0; if (InitSDCard()) { struct dirent* dent; FATDirHandle* d = static_cast<FATDirHandle*>( opendir(dirname) ); if (d!=0) { while ( (dent = readdir(d))!=NULL ) { Watchdog::kick(); // don't reset if ( (d->filinfo()->fattrib & AM_DIR)!=0 ) { // a subdirectory std::string dnm(dirname); dnm += "/"; dnm += dent->d_name; uint32_t sdnf; float sdtb; GetDirProps(dnm.c_str(), sdnf, sdtb); nfiles += sdnf; totbytes += sdtb; } else { // a file ++nfiles; totbytes += d->filinfo()->fsize; } } closedir(d); } } #ifdef DEBUG printf("GetDirProps: %s :: nf=%u, tb=%g\r\n", dirname, nfiles, totbytes); #endif } bool SnSDUtils::WriteHeartbeatTo(FILE* file, const uint32_t time, const uint32_t num) { Watchdog::kick(); // don't reset if (file!=0) { if (InitSDCard()) { const bool r1 = SnHeaderFrame::WriteTo(file, SnHeaderFrame::kHeartbeatCode, SnHeartbeatFrame::SizeOf(SnHeartbeatFrame::kIOVers)); const bool r2 = SnHeartbeatFrame::WriteTo(file, time, num); return (r1 && r2); } } return false; } bool SnSDUtils::WriteTrigWaitWinTime(FILE* file, SnClockSetFrame& clkset, const bool isStart) { Watchdog::kick(); // don't reset if (file!=0) { if (InitSDCard()) { bool ok = SnHeaderFrame::WriteTo(file, (isStart) ? (SnHeaderFrame::kFileTrgStrtCode) : (SnHeaderFrame::kFileTrgStopCode), clkset.SizeOf()); ok &= (SnCommWin::kOkMsgSent == clkset.WriteTo(file)); return ok; } } return false; } bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf, const SnEventFrame& evt, const SnConfigFrame& conf) { Watchdog::kick(); // don't reset // write event to SD card bool ret = false; if (efile!=0) { if (InitSDCard()) { uint8_t sLoseLSB=0, sLoseMSB=0; uint16_t sWvBase=0; conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase); SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB)); ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase); fflush(efile); } } return ret; } bool SnSDUtils::WriteConfig(FILE* efile, const SnConfigFrame& conf) { Watchdog::kick(); // don't reset if (efile!=0) { if (InitSDCard()) { SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, conf.SizeOf(SnConfigFrame::kIOVers)); conf.WriteTo(efile); return true; } } return false; } void SnSDUtils::DeleteFile(FILE*& f, const char* fname) { #ifdef DEBUG printf("try to delete %s at %p\r\n",fname,f); #endif Watchdog::kick(); // don't reset if (InitSDCard()) { if (f!=0) { fclose(f); f=0; } std::string fn(""); if (GetFullFilename(fname, fn)) { #ifdef DEBUG printf("calling remove [%s]\r\n",fn.c_str()); #endif remove(fn.c_str()); } } } void SnSDUtils::DeleteFilesOfRun(const uint32_t run) { #ifdef DEBUG printf("deleteing files of run %lu\r\n",run); #endif Watchdog::kick(); // don't reset uint32_t rdlen(0); std::string rdnm( GetSubDirFor(run, 0, rdlen, false) ); DeleteAllFiles(rdnm.c_str()); } void SnSDUtils::DeleteAllFiles(const char* dirname) { #ifdef DEBUG printf("deleting ALL files in %s\r\n",dirname); #endif Watchdog::kick(); // don't reset if (InitSDCard()) { DIR* d; struct dirent* dent; if ( (d = opendir( dirname ))!=NULL ) { FATDirHandle* dir = static_cast<FATDirHandle*>(d); while ( (dent = readdir(d))!=NULL ) { Watchdog::kick(); // don't reset if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) { // a subdirectory std::string dnm(dirname); dnm += "/"; dnm += dent->d_name; // delete all the files in this new subdir #ifdef DEBUG printf("call DeleteAllFiles(%s)\r\n",dnm.c_str()); #endif DeleteAllFiles(dnm.c_str()); } else if (strncmp(dent->d_name, "SnEvts", 6)==0) { // a data file (delete it) const bool isCurFile = (strcmp(dent->d_name, GetCurFileName())==0); if (isCurFile==false) { // don't delete the current file FILE* f(0); // dummy DeleteFile(f, dent->d_name); } } } // loop over stuff in this dir closedir(d); DeleteDirIfEmpty(dirname); } } } bool SnSDUtils::DeleteDirIfEmpty(const char* dirname) { #ifdef DEBUG printf("DeleteDirIfEmpty(%s)\r\n",dirname); #endif Watchdog::kick(); // don't reset bool doDel = false; if (InitSDCard()) { DIR* d; struct dirent* dent; if ( (d = opendir(dirname))!=NULL ) { dent = readdir(d); if ( dent==NULL ) { // then this directory is empty static const size_t subdsz = strlen(kSDsubDir); // just double check that this directory is // a subdirectory of the data dir if (strlen(dirname)>subdsz) { doDel = true; } } // else this dir isn't empty closedir(d); if (doDel) { #ifdef DEBUG printf("removing directory [%s]\r\n",dirname); #endif remove(dirname); } } } return doDel; } SnCommWin::ECommWinResult SnSDUtils::SendOneFile(const char* dfn, SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow) { #ifdef DEBUG printf("SendOneFile (%s)\r\n",dfn); #endif Watchdog::kick(); // don't reset SnCommWin::ECommWinResult res = SnCommWin::kOkMsgSent; // open the file const bool isCurFile = (strcmp(dfn, GetCurFileName())==0); FILE* f(0); if (isCurFile) { // file must already be written out! f = GetCurFile(); } else { f = OpenExistingFile(dfn, false, false); } #ifdef DEBUG printf("SendOneFile: isCurFile=%d, f=%p, fn=%s\r\n", (int)isCurFile, (void*)f, dfn); #endif uint8_t hndres = SnHeaderFrame::kHnShFailNonCode; if (f!=0) { #ifdef DEBUG printf("SendOneFile: calling SendDataFromFile\r\n"); #endif res = comm->SendDataFromFile(f, dfn, curConf, evt, pow, buf, bsize, 0, timeout, &hndres); if (isCurFile) { // move (back) to the end of the file // altho hopefully no writing will happen after this fseek(fgCurFile, 0, SEEK_END); } } #ifdef DEBUG printf("isCurFile=%d, res=%d, deleting=%d, hndres=%02x\r\n", (int)isCurFile, (int)res, (int)(curConf.IsDeletingFiles()), hndres); #endif return res; } bool SnSDUtils::ClearRunSeqList() { Watchdog::kick(); // don't reset if (InitSDCard()) { FILE* rslistf = fopen(kRunSeqListFilenm,"w"); const bool ok = rslistf!=0; fclose(rslistf); #ifdef DEBUG printf("ClearRunSeqList. ok=%s\r\n",(ok?"true":"false")); #endif return ok; } return false; } bool SnSDUtils::AddToRunSeqList(const uint32_t run, const uint16_t seq) { Watchdog::kick(); // don't reset if (InitSDCard()) { FILE* rslistf = fopen(kRunSeqListFilenm,"a"); bool ok = false; if (rslistf!=0) { ok = fprintf(rslistf, "%u %hu\n", run, seq) > 0; ok &= 0==ferror(rslistf); #ifdef DEBUG printf("AddToRunSeqList: run=%u, seq=%hu, ok=%s\r\n", run, seq, (ok?"true":"false")); #endif } fclose(rslistf); return ok; } return false; } SnCommWin::ECommWinResult SnSDUtils::SendFileWithRunSeq(SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, const uint32_t run, const uint16_t seq) { #ifdef DEBUG printf("SendFileWithRunSeq\r\n"); #endif Watchdog::kick(); // don't reset // get the file name std::string dfn = GetOutFileName(SnConfigFrame::GetMacAddress(), run, seq); // send it const SnCommWin::ECommWinResult res = SendOneFile(dfn.c_str(), comm, timeout, buf, bsize, curConf, evt, pow); // see if we need to remove this directory now if (curConf.IsDeletingFiles()) { // get run/seq directory name uint32_t rdlen(0); std::string rdnm( GetSubDirFor(run, seq, rdlen, true) ); #ifdef DEBUG printf("Checking removal of dir [%s]\r\n",rdnm.c_str()); #endif if ( DeleteDirIfEmpty(rdnm.c_str()) ) { // removed the seq dir. do we need to remove // the run dir too? rdnm = GetSubDirFor(run, seq, rdlen, false); #ifdef DEBUG printf("Checking removal of dir [%s]\r\n",rdnm.c_str()); #endif DeleteDirIfEmpty(rdnm.c_str()); } } return res; } SnCommWin::ECommWinResult SnSDUtils::SendFilesInRunSeqList(SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow) { #ifdef DEBUG printf("SendFilesInRunSeqList\r\n"); #endif SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent; Watchdog::kick(); // don't reset if (InitSDCard()) { // open up the run/seq list file and send each corresponding file FILE* rslistf = fopen(kRunSeqListFilenm,"r"); #ifdef DEBUG printf("fslistf=%p\r\n",(void*)rslistf); #endif if (rslistf!=0) { uint32_t run(0); uint16_t seq(0); while ( (feof(rslistf)==0) && (ferror(rslistf)==0) ) { #ifdef DEBUG printf("feof=%d, ferror=%d\r\n", (int)(feof(rslistf)), (int)(ferror(rslistf))); #endif Watchdog::kick(); // don't reset const int nfilled = fscanf(rslistf, "%u %hu\n", &run ,&seq); #ifdef DEBUG printf("nfilled=%d\r\n", nfilled); #endif if ( 2==nfilled ) { #ifdef DEBUG printf("run=%u, seq=%hu\r\n",run,seq); #endif SnCommWin::ECommWinResult res = SendFileWithRunSeq(comm, timeout, buf, bsize, curConf, evt, pow, run, seq); if ((res<rs) || (res==SnCommWin::kOkStopComm)) { rs = res; } // don't necessarily stop if rs is bad. don't want one bad file to // prevent sending the others if (rs<=SnCommWin::kFailTimeout) { break; } else if (rs==SnCommWin::kOkStopComm) { break; } } } // do we need to clear the list? if (curConf.IsRunSeqListOneCommWinOnly()==false) { if (rs >= SnCommWin::kOkMsgSent) { // all sent ok ClearRunSeqList(); } } } fclose(rslistf); } return rs; } SnCommWin::ECommWinResult SnSDUtils::SendPartOfRun(SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, const uint32_t run, const uint16_t minseq, const uint16_t maxseq) { // send files with run number 'run' // and seq number in [minseq,maxseq] (min/max inclusive) #ifdef DEBUG printf("SendPartOfRun\r\n"); #endif Watchdog::kick(); // don't reset SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent; for (uint16_t seq=minseq; seq<=maxseq; ++seq) { Watchdog::kick(); // don't reset SnCommWin::ECommWinResult res = SendFileWithRunSeq(comm, timeout, buf, bsize, curConf, evt, pow, run, seq); if ((res<rs) || (res==SnCommWin::kOkStopComm)) { rs = res; } // don't necessarily stop if rs is bad. don't want one bad file to // prevent sending the others if (rs<=SnCommWin::kFailTimeout) { break; } else if (rs==SnCommWin::kOkStopComm) { break; } } return rs; } SnCommWin::ECommWinResult SnSDUtils::SendAllOfRun(SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, const uint32_t runnum) { // send all files in a run Watchdog::kick(); // don't reset // get the run dir uint32_t rdlen(0); std::string rdnms ( GetSubDirFor(runnum, 0, rdlen, false) ); return SendAllFiles(comm, timeout, buf, bsize, curConf, evt, pow, rdnms.c_str()); } SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm, const uint32_t timeout, char* const buf, const uint32_t bsize, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, const char* dirname) { // send all files in the specified directory Watchdog::kick(); // don't reset SnCommWin::ECommWinResult rs = SnCommWin::kUndefFail; if (InitSDCard()) { rs = SnCommWin::kOkMsgSent; DIR* d; struct dirent* dent; if ( (d = opendir( dirname ))!=NULL ) { FATDirHandle* dir = static_cast<FATDirHandle*>(d); while ( (dent = readdir(d))!=NULL ) { Watchdog::kick(); // don't reset SnCommWin::ECommWinResult res = rs; if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) { // a subdirectory std::string dnm(dirname); dnm += "/"; dnm += dent->d_name; // send all the files in this new subdir res = SendAllFiles(comm, timeout, buf, bsize, curConf, evt, pow, dnm.c_str()); } else if (strncmp(dent->d_name, "SnEvts", 6)==0) { // a data file (send it) res = SendOneFile(dent->d_name, comm, timeout, buf, bsize, curConf, evt, pow); } if ((res<rs) || (res==SnCommWin::kOkStopComm)) { rs = res; } // don't necessarily stop if rs is bad. don't want one bad file to // prevent sending the others if (rs<=SnCommWin::kFailTimeout) { break; } else if (rs==SnCommWin::kOkStopComm) { break; } } // loop over stuff in this directory closedir(d); // see if we need to remove this directory now if (curConf.IsDeletingFiles()) { DeleteDirIfEmpty(dirname); } } } return rs; }