Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnCommWin.cpp
- Committer:
- uci1
- Date:
- 2013-05-23
- Revision:
- 36:87865913ae6f
- Parent:
- 27:efc4d654b139
- Child:
- 37:ff95e7070f26
File content as of revision 36:87865913ae6f:
#include "SnCommWin.h" #include "SnHeaderFrame.h" #include "SnConfigFrame.h" #include "SnEventFrame.h" #include "SnPowerFrame.h" #include "SnStatusFrame.h" #include "SnSDUtils.h" #include "SnConstants.h" #include "SnCRCUtils.h" #include <algorithm> #include <ctype.h> extern "C" void mbed_reset(); #define DEBUG const char* SnCommWin::kLocalDir = "/local"; const char* SnCommWin::kDelAllConfCodeStr = "fj2io32FIJ(#jd;;.O@++/]ewavk2[49ojv"; const uint8_t SnCommWin::kDelAllConfCodeLen = 35; // length of the above string uint32_t SnCommWin::GetConnectTimeout() const { return kConnectTimeout; } uint32_t SnCommWin::GetListenTimeout() const { return kListenTimeout; } bool SnCommWin::IsTimedOut(const uint32_t timeout_clock) const { if (timeout_clock==0) { // for not obeying timeout option return false; } else { const uint32_t ct = time(0); if ( (ct==0) || (fabs(static_cast<double>(timeout_clock-ct))>kSecsPerDay) ) { // clock problems! // timeout now. hope the clock problems // get fixed in the next comm window return true; } else { return (ct>timeout_clock); } } } SnCommWin::ECommWinResult SnCommWin::SendData(SnConfigFrame& conf, SnEventFrame& evt, SnPowerFrame& pow, char* const genBuf, const uint32_t bsize, const uint32_t timeout, const uint32_t handshakeTimeout) { #ifdef DEBUG printf("SnCommWin::SendData\r\n"); #endif ECommWinResult res = kUndefFail; if ( (GetCommType() != SnConfigFrame::kIrid) || (conf.IsForcingSBDdata()) ) { // only send large amounts if we're not communicating by Iridum, // or if we are being forced to send the data over SBD if (conf.IsSendingAllFiles()) { #ifdef DEBUG printf("sending all files\r\n"); #endif res = SnSDUtils::SendAllFiles(this, timeout, genBuf, bsize, conf, evt, pow, handshakeTimeout); } else { if (conf.GetCommSendData()==0) { #ifdef DEBUG printf("no data to send\r\n"); #endif res = kOkNoMsg; } else { const uint32_t nev = (conf.GetCommSendData()>0) ? conf.GetCommSendData() // send N events : 0u; // send all events in last file #ifdef DEBUG printf("calling SendData. f=%s, nev=%u\r\n",SnSDUtils::GetCurFileName(), nev); #endif res = SendData(SnSDUtils::GetCurFile(), SnSDUtils::GetCurFileName(), conf, evt, pow, genBuf, bsize, nev, timeout, handshakeTimeout); #ifdef DEBUG printf("after send data cur file, res=%d\r\n",(int)res); #endif } } } else { return kOkNoMsg; } return res; } SnCommWin::ECommWinResult SnCommWin::SendData(FILE* inf, const char* infn, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, char* const genBuf, const uint32_t bsize, const uint32_t nevts, const uint32_t timeout_clock, const uint32_t handshakeTimeout, uint8_t* hndres) { // nevts==0 ==> send all events // handshakeTimeout is never a clock time -- always a delta(t) #ifdef DEBUG printf("SnCommWin::SendData file (%p), fn=%s\r\n",inf,infn); #endif ECommWinResult res = kUndefFail; bool didDel = false; if (inf!=0) { #ifdef DEBUG printf("sending file name %s\r\n",infn); #endif // send the file name res = SendFilename(infn, genBuf, timeout_clock); if (res>kAllFails) { if (genBuf!=0) { #ifdef DEBUG printf("calling send file contents\r\n"); #endif // send the contents res = SendFileContents(inf, curConf, evt, pow, genBuf, nevts, timeout_clock); #ifdef DEBUG printf("res=%d (fails=%d)\r\n",(int)res,(int)kAllFails); #endif if (res>kAllFails) { #ifdef DEBUG printf("calling wait handshake\r\n"); #endif // wait for handshake uint8_t hndshk(0); uint32_t hndshkLen(0); res = WaitHandshake(curConf, handshakeTimeout, genBuf, bsize, hndshk, &hndshkLen); if (hndres!=0) { *hndres = hndshk; } #ifdef DEBUG printf("res=%d, nevts=%u, isdel=%d, inf=%p, curfile=%p, hndshk=%02x\r\n", res, nevts, curConf.IsDeletingFiles(), inf, SnSDUtils::GetCurFile(), hndshk); #endif if ( (res==SnCommWin::kOkWithMsg) // got handshake && (nevts==0) // sent whole file && (inf!=SnSDUtils::GetCurFile()) ) { // not current file if ( curConf.IsDeletingFiles() // want to delete && (hndshk==SnHeaderFrame::kHnShOkComplCode)) { // whole file received // delete it #ifdef DEBUG printf("deleting file %p, %s\r\n",inf,infn); #endif SnSDUtilsWhisperer::DeleteFile(inf, infn); didDel=true; } else if ( hndshk==SnHeaderFrame::kHnShOkStopCode ) { res = SnCommWin::kOkStopComm; } else if ( (hndshk==SnHeaderFrame::kHnShOkDelAlCode) || (hndshk==SnHeaderFrame::kHnShOkDelRnCode) ) { if ( GetDeleteAllConfirmCode(curConf, kDelAllConfCodeLen, handshakeTimeout, genBuf, bsize) ) { if (hndshk==SnHeaderFrame::kHnShOkDelAlCode) { SnSDUtilsWhisperer::DeleteAllFiles(); } else if (hndshk==SnHeaderFrame::kHnShOkDelRnCode) { SnSDUtilsWhisperer::DeleteFilesOfRun(hndshkLen); } res = SnCommWin::kOkStopComm; } } } } } } } else { #ifdef DEBUG printf("inf=0!\r\n"); #endif } if ( (inf!=SnSDUtils::GetCurFile()) && (didDel==false) ) { SnSDUtils::CloseOutputFile(inf); } if ( IsTimedOut(timeout_clock) ) { if ( kFailTimeout < res ) { res = kFailTimeout; } } return res; } bool SnCommWin::GetDeleteAllConfirmCode(const SnConfigFrame& conf, const uint32_t length, const uint32_t timeout, char* const buf, const uint32_t bsize) { bool ret = false; // ensure we don't wait forever const uint32_t to = ((timeout>0) && (timeout<kAbsMaxTimer)) ? conf.GetTimeoutTime(time(0), timeout) : conf.GetTimeoutTime(time(0), kListenTimeout); #ifdef DEBUG printf("GetDeleteAllConfirmCode, to=%u\r\n",to); #endif // better pull all the bytes no matter the buffer size const uint32_t ll = (bsize<length) ? bsize : length; int mlen = 0; while ( mlen<length ) { mlen += ReceiveAll(buf, ll, to); if (IsTimedOut(to)) { break; } } if (mlen==length) { const char* b = buf; const char* c = kDelAllConfCodeStr; bool match = true; for (uint8_t i=0; (i<kDelAllConfCodeLen) && match; ++i, ++b, ++c) { match = ((*b)==(*c)); } ret = match; } return ret; } SnCommWin::ECommWinResult SnCommWin::WaitHandshake(const SnConfigFrame& conf, const uint32_t timeout, char* const buf, const uint32_t bsize, uint8_t& hndShkCode, uint32_t* hndShkLen) { // ensure we don't wait forever const uint32_t to = ((timeout>0) && (timeout<kAbsMaxTimer)) ? conf.GetTimeoutTime(time(0), timeout) : conf.GetTimeoutTime(time(0), kListenTimeout); #ifdef DEBUG printf("WaitHandshake, to=%u\r\n",to); #endif const int mlen = ReceiveAll(buf, SnHeaderFrame::SizeOf(), to); if (mlen>0 && static_cast<uint32_t>(mlen) == SnHeaderFrame::SizeOf()) { uint32_t msgLen=0; const char* b = buf; SnHeaderFrame::ReadFrom(b, hndShkCode, msgLen); #ifdef DEBUG printf("got handshake code=%02x, len=%u\r\n",hndShkCode,msgLen); #endif if ((hndShkCode & SnHeaderFrame::kHndShkBits)!=0) { if (hndShkLen!=0) { *hndShkLen = msgLen; } return SnCommWin::kOkWithMsg; } else { // TODO: somehow handle unexpected message? return SnCommWin::kUnexpectedRec; } } return SnCommWin::kOkNoMsg; } SnCommWin::ECommWinResult SnCommWin::GetFilename(const uint32_t timeout, char* const buf, const uint32_t namelen) { // called by GetConfig upon receipt of a kMbedFilenameCode #ifdef DEBUG printf("GetMbedFile, to=%u\r\n",timeout); #endif const int mlen = ReceiveAll(buf, namelen, timeout); if (mlen>0 && static_cast<uint32_t>(mlen) == namelen) { return SnCommWin::kOkWithMsg; } return SnCommWin::kUnexpectedRec; } void SnCommWin::CapitalizeInPlace(std::string::iterator s, const std::string::const_iterator send) { static const char upd = 'a' - 'A'; // a>A for (; s!=send; ++s) { if ( ((*s)>='a') && ((*s)<='z') ) { (*s) -= upd; } } } SnCommWin::ECommWinResult SnCommWin::GetLocalFile(std::string fname, char* const buf, const uint32_t bsize, const uint32_t timeout) { // get a file and save it locally with the specified name // get the header for the file uint8_t mcode=0; uint32_t mlen=0; SnCommWin::ECommWinResult res = GetHeader(timeout, buf, bsize, mcode, mlen); if ( (res>=kOkWithMsg) && (mcode==SnHeaderFrame::kMbedFileCode) ) { #ifdef DEBUG printf("Got mbed file header. File length = %u\r\n",mlen); #endif // got the header.. make the file.. // make the file name ALLCAPS, since LocalFileSystem will do it anyway CapitalizeInPlace(fname.begin(), fname.end()); // now ensure the file name is 8.3 only -- for LocalFileSystem const size_t ldlen = strlen(kLocalDir); // 12 = 8.3 filename format, 1 for / and 1 for \0 const uint32_t fbs = ldlen+1+12+1; char fnb[fbs]; memset(fnb, 0, sizeof(char)*fbs); char* fb = fnb; memcpy(fb, kLocalDir, ldlen); fb+=ldlen; // /local memset(fb, '/', 1); fb+=1; // / strncpy(fb, fname.c_str(), 8); fb+=8; // FILENAME *fb = '.'; ++fb; // . strncpy(fb, fname.c_str()+fname.size()-3, 3); // EXT // all that just for the file name! FILE* lf = fopen(fnb,"wb"); #ifdef DEBUG printf("tried to open file [%s]. lf=%p\r\n",fnb,(void*)lf); #endif // get all the data and dump it into the file int b = 0, toget = 0; while ( mlen>b ) { if (IsTimedOut(timeout)) { #ifdef DEBUG printf("timeout while getting file\r\n"); #endif res = kFailTimeout; break; } toget = mlen - b; if (toget>bsize) { toget = bsize; } const int got = ReceiveAll(buf, toget, timeout); if (lf!=NULL) { #ifdef DEBUG printf("writing %d bytes to file\r\n", got); #endif SnBitUtils::WriteTo(lf, buf, got); } b += got; } uint32_t crc=0; if (lf!=NULL) { // calculate the crc from what's actually in the file fclose(lf); // to flush it #ifdef DEBUG printf("fopen: %s\r\n",fnb); #endif lf = fopen(fnb,"rb"); fseek(lf, 0, SEEK_END); int32_t fend = ftell(lf); fseek(lf, 0, SEEK_SET); char c; for (int32_t i=0; i<fend; ++i) { SnBitUtils::ReadFrom(lf, c); if (feof(lf)==0 && ferror(lf)==0) { crc = update_crc32_xfer(crc, c); } else { break; } } fclose(lf); #ifdef DEBUG printf("closed file. crc = %u\r\n", crc); #endif } #ifdef DEBUG printf("mlen=%u, b=%d, eq=%s\r\n",mlen,b, (mlen==b)?"true":"false"); #endif if ( mlen!=b ) { if (res > kUnexpectedRec) { res = kUnexpectedRec; } // otherwise it's already worse } else { // check that the file is ok // get the checksum res = GetHeader(timeout, buf, bsize, mcode, mlen); if ( (res>=kOkWithMsg) && (mcode==SnHeaderFrame::kMbedFileChksCode) ) { #ifdef DEBUG printf("received chksum=%u, crc=%u, eq=%s\r\n", mlen,crc,(crc==mlen)?"true":"false"); #endif if (crc != mlen) { #ifdef DEBUG printf("checksums differ! unexpected.\r\n"); #endif res = kUnexpectedRec; // important! } } } //TODO: REMOVE /* char dbg[250]; memset(dbg, 0, 250); char* dd = buf; sprintf(dbg,"lf=%s (%p), my crc=%d, b=%d, mlen=%d\r\n",fnb,(void*)lf,crc,crc,b,mlen); SnHeaderFrame::WriteTo(dd, SnHeaderFrame::kStringCode, strlen(dbg)); strcpy(buf+SnHeaderFrame::SizeOf(),dbg); SendAll(buf, SnHeaderFrame::SizeOf() + strlen(dbg), timeout); */ /////////// if (lf!=NULL) { if ( res<kOkWithMsg ) { // timeout, bad checksum, something else bad? #ifdef DEBUG printf("removing %s\r\n",fnb); #endif remove(fnb); // delete the file } else { // if we got a new program, remove the old ones. // (schedule myself for immediate de-resolution) // // first just count how many we would save const uint16_t nSavedBins = LoopLocalDirBinFiles(false, fname); #ifdef DEBUG printf("nSavedBins=%hu",nSavedBins); #endif if (nSavedBins==1) { // ok. new program will be the only one. remove the others // hope the new program works! LoopLocalDirBinFiles(true, fname); #ifdef DEBUG printf("rebooting\r\n"); #endif // goodbye cruel world, it's over. walk on by... mbed_reset(); } } } } return res; } int16_t SnCommWin::LoopLocalDirBinFiles(const bool doRemove, const std::string& fname) { // loop over the local directory, count the BIN files that match 'fname' // // fname is assumed to be all caps already! // // if doRemove==true, will actually delete non-matching files // // return number of non-matching files uint16_t nSavedBins = 0; DIR* d( opendir(kLocalDir) ); struct dirent* dent; if ( d!=NULL ) { while ( (dent = readdir(d))!=NULL ) { const size_t flen = strlen(dent->d_name); const char* dext = dent->d_name + flen - 4; if ( strncmp(dext,".BIN",4)==0 || strncmp(dext,".bin",4)==0 ) { // ends with .BIN if (strncmp(dent->d_name, fname.c_str(), fname.size())!=0) { // some other mbed program than our new one std::string dfn(kLocalDir); dfn += "/"; dfn += dent->d_name; if (doRemove) { remove(dfn.c_str()); } } else { ++nSavedBins; } } // else not an mbed program } closedir(d); } return nSavedBins; } SnCommWin::ECommWinResult SnCommWin::GetHeader(const uint32_t timeOut, char* const buf, const uint32_t bsize, uint8_t& mcode, uint32_t& mlen) { SnCommWin::ECommWinResult res = SnCommWin::kUndefFail; if (bsize>=SnHeaderFrame::kMaxSizeOf) { // get header const int hlen = ReceiveAll(buf, SnHeaderFrame::SizeOf(), timeOut); if (hlen>0 && static_cast<uint32_t>(hlen)==SnHeaderFrame::SizeOf()) { mcode=0; mlen=0; const char* b = buf; SnHeaderFrame::ReadFrom(b, mcode, mlen); #ifdef DEBUG printf("mcode=%02x, mlen=%u\r\n", mcode, mlen); #endif res = SnCommWin::kOkWithMsg; } } return res; } SnCommWin::ECommWinResult SnCommWin::GetConfig(SnConfigFrame& conf, const uint32_t timeOut, char* const confBuf, const uint32_t bsize) { // confBuf assumed to alread be of allocated size #ifdef DEBUG printf("GetConfig, to=%u\r\n",timeOut); #endif SnCommWin::ECommWinResult res = SnCommWin::kUndefFail; if (bsize>=SnConfigFrame::kMaxSizeOf) { // get header uint8_t mcode=0; uint32_t mlen=0; res = GetHeader(timeOut, confBuf, bsize, mcode, mlen); if (res>=SnCommWin::kOkWithMsg) { if (mcode==SnHeaderFrame::kNoConfigCode) { // no config to get res = SnCommWin::kOkWthMsgNoConf; } else if (mcode==SnHeaderFrame::kMbedFilenameCode) { res = GetFilename(timeOut, confBuf, mlen); if (res>kAllFails) { std::string fname(confBuf, mlen); // the filename #ifdef DEBUG printf("got filename = [%s]\r\n", fname.c_str()); #endif res = GetLocalFile(fname, confBuf, bsize, timeOut); } } else if (mcode!=SnHeaderFrame::kConfigCode) { res = SnCommWin::kUnexpectedRec; } else { // get config const int clen = ReceiveAll(confBuf, mlen, timeOut); if (clen>0 && static_cast<uint32_t>(clen)==mlen) { const char* b = confBuf; conf.ReadFrom(b); res = SnCommWin::kOkWithMsg; } else { res = SnCommWin::kUnexpectedRec; } } } else { // not a problem if we get nothing (or no config) res = SnCommWin::kOkNoMsg; } } return res; } SnCommWin::ECommWinResult SnCommWin::SendStatus(const SnConfigFrame& conf, const SnEventFrame& evt, const SnPowerFrame& pow, const uint16_t seq, const float thmrate, const float evtrate, char* const genBuf, const uint32_t timeout_clock) { // TODO: check if connected? #ifdef DEBUG printf("########### Send Status\r\n"); #endif uint8_t loseLSB=0, loseMSB=0; uint16_t wvBase=0; conf.GetPackParsFor(GetCommType(), loseLSB, loseMSB, wvBase); const uint32_t ssize = SnStatusFrame::SizeOf(SnStatusFrame::kIOVers, conf); char* b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kStatusCode, ssize); SnStatusFrame::WriteTo(b, conf, evt, genBuf, seq, thmrate, evtrate, loseLSB, loseMSB, wvBase); SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, pow.SizeOf(SnPowerFrame::kIOvers)); pow.WriteTo(b); int msiz = b-genBuf; #ifdef DEBUG printf("calling SendAll (status)\r\n"); #endif int mlen = SendAll(genBuf, msiz, timeout_clock); #ifdef DEBUG printf("status frame:\r\n"); for (uint32_t i=0; i<msiz; i++) { printf("%02X ",genBuf[i]); } printf("\r\n"); #endif if (mlen==msiz) { #ifdef DEBUG printf("status+power sent\r\n"); #endif // event compression parameters must be the same // as those sent in the status update b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kEventCode, evt.SizeOf(SnEventFrame::kIOVers, loseLSB, loseMSB)); b = evt.WriteTo(b, loseLSB, loseMSB, wvBase); msiz = b-genBuf; #ifdef DEBUG printf("calling SendAll (event) %d:\r\n",msiz); for (uint32_t i=0; i<msiz; i++) { printf("%02X ",genBuf[i]); } printf("\r\n"); #endif mlen = SendAll(genBuf, msiz, timeout_clock); if (mlen==msiz) { return SnCommWin::kOkMsgSent; } } return SnCommWin::kFailPartSent; } SnCommWin::ECommWinResult SnCommWin::SendString(const char* str, const uint32_t timeout) { #ifdef DEBUG printf("SnCommWin::SendString %s\r\n",str); #endif const size_t rlen = strlen(str); const size_t slen = rlen > kMaxStrLen ? kMaxStrLen : rlen; const int msiz = slen+SnHeaderFrame::SizeOf(); char* const ts = new char[msiz]; char* t = ts; SnHeaderFrame::WriteTo(t, SnHeaderFrame::kStringCode, slen); strncpy(t, str, slen); const int mlen = SendAll(ts, msiz, timeout); delete[] ts; return (msiz==mlen) ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent; } SnCommWin::ECommWinResult SnCommWin::SendFilename(const char* inf, char* const genBuf, const uint32_t timeout_clock) { #ifdef DEBUG printf("SnCommWin::SendFilename %s\r\n",inf); #endif // remove the directory const char* fn = strrchr(inf, '/'); if (fn==0) { // no directory fn = inf; } else if (fn!=inf) { ++fn; // move past the '/' if it was found } #ifdef DEBUG printf("send %s\r\n",fn); #endif const size_t flen = strlen(fn); char* b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFilenameCode, flen); b = SnBitUtils::WriteTo(b, fn, flen); const int msiz = b-genBuf; const int mlen = SendAll(genBuf, msiz, timeout_clock); #ifdef DEBUG printf("time = %u, timeout = %u\r\n",time(0), timeout_clock); #endif return (msiz==mlen) ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent; } int SnCommWin::SendFileBlock(FILE* inf, const uint8_t blockHeaderCode, const uint32_t blockSize, char* const genBuf, const uint32_t timeout) { // sends the block from the file. does not check if the file has sufficient bytes // this should be done before calling this function // (where the number of bytes in the file can be cached) char* b = genBuf; SnHeaderFrame::WriteTo(b, blockHeaderCode, blockSize); SnBitUtils::ReadFrom(inf, b, blockSize); #ifdef DEBUG printf("Sending block hc %02x, len=%u\r\n",blockHeaderCode,blockSize+SnHeaderFrame::SizeOf()); #endif return SendAll(genBuf, blockSize+SnHeaderFrame::SizeOf(), timeout); } SnCommWin::ECommWinResult SnCommWin::SendFileContents(FILE* inf, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, char* const genBuf, uint32_t nevts, const uint32_t timeout_clock) { // firstEvt==0 ==> start at beginning // nevts==0 ==> all events #ifdef DEBUG printf("SendFileContents (byte streaming)\r\n"); #endif // store position in file so we can go back to it afterwards // this is probably not necessary, because if this file is open // in write-only mode, we're screwed.. const int fpos = ftell(inf); if (fpos>0) { fseek(inf, 0, SEEK_SET); } // how many bytes? fseek(inf, 0, SEEK_END); // go to end const int fend = ftell(inf); fseek(inf, 0, SEEK_SET); // go to start #ifdef DEBUG printf("fend=%d\r\n",fend); printf("fpos=%d\r\n",fpos); #endif // variables used when sending data char* b = genBuf; int msiz, mlen; // count number of events / power readings sent uint32_t evtsSent=0, powsSent=0; // first is the file header, which has no SnHeaderFrame msiz = SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers); bool ok = (ftell(inf)+msiz)<=fend; if (ok) { mlen = SendFileBlock(inf, SnHeaderFrame::kFileHeadrCode, msiz, genBuf, timeout_clock); ok &= (msiz+SnHeaderFrame::SizeOf())==mlen; #ifdef DEBUG printf("sent file header. ok=%d\r\n",(int)ok); #endif // the header info for each block uint8_t hcode; uint32_t hlen; // now just loop through file and send each block bool fok = true; while ( fok && (feof(inf)==0) && (ferror(inf)==0) && ((ftell(inf)+SnHeaderFrame::SizeOf())<=fend) ) { // read the header for the block SnSDUtils::ReadBlockHeader(inf, hcode, hlen); fok &= (ftell(inf)+hlen)<=fend; #ifdef DEBUG printf("new block: hc=%02x, hl=%u, ftell=%d, fend=%d, " "ok=%d, fok=%d\r\n", hcode, hlen, ftell(inf), fend, (int)ok, (int)fok); #endif if (ok) { // send the block // TODO: repack events? msiz = hlen + SnHeaderFrame::SizeOf(); mlen = SendFileBlock(inf, hcode, hlen, genBuf, timeout_clock); ok &= msiz==mlen; if (ok) { if (hcode==SnHeaderFrame::kEventCode) { ++evtsSent; if (nevts>0) { if (evtsSent>=nevts) { #ifdef DEBUG printf("send %u events. stop\r\n",evtsSent); #endif break; } } } else if (hcode==SnHeaderFrame::kPowerCode) { ++powsSent; } } else { #ifdef DEBUG printf("not ok when sending hcode=%02x\r\n",hcode); #endif } // if ok after sending block } // if ok after sending block header } // loop over file contents } else { // otherwise file size not sufficient for file header // so it's either 0 or corrupted. // proceed as normal even tho no contents were sent. // if we're deleting files, this one will be deleted. ok = true; } #ifdef DEBUG printf("loop done. ok=%d\r\n",(int)ok); #endif // send number of events sent #ifdef DEBUG printf("sending evtsSent (%u)\r\n",evtsSent); #endif b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, sizeof(uint32_t)); b = SnBitUtils::WriteTo(b, evtsSent); msiz = b - genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= msiz==mlen; #ifdef DEBUG printf("ok=%d (msiz=%d, mlen=%d)\r\n", (int)ok, msiz, mlen); #endif // send number of power readings sent #ifdef DEBUG printf("sending powsSent (%u)\r\n",powsSent); #endif b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNpwrsCode, sizeof(uint32_t)); b = SnBitUtils::WriteTo(b, powsSent); msiz = b - genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= msiz==mlen; #ifdef DEBUG printf("ok=%d (msiz=%d, mlen=%d)\r\n", (int)ok, msiz, mlen); #endif // put file position back fseek(inf, fpos, SEEK_SET); #ifdef DEBUG printf("end contents: ok=%d\r\n",(int)ok); #endif return ok ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent; } /* SnCommWin::ECommWinResult SnCommWin::SendFileContents(FILE* inf, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, char* const genBuf, uint32_t nevts, const uint32_t timeout_clock, const uint32_t firstEvt) { printf("comm win send file contents\r\n"); // firstEvt==0 ==> start at beginning // nevts==0 ==> all events const int fpos = ftell(inf); if (fpos>0) { fseek(inf, 0, SEEK_SET); } // how many bytes? fseek(inf, 0, SEEK_END); // go to end const int fend = ftell(inf); fseek(inf, 0, SEEK_SET); // go to start printf("fend=%d\r\n",fend); printf("fpos=%d\r\n",fpos); // get file header uint64_t macadr; uint32_t run; uint16_t seq; bool ok = (ftell(inf)+SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers))<=fend; if (ok) { SnSDUtils::ReadFileHeader(inf, macadr, run, seq, &pow); printf("read file header: run %u, seq %hu\r\n",run,seq); } printf(">>> file hdr read ftell(inf)=%d\r\n",ftell(inf)); // check block uint8_t hcode; uint32_t hlen; ok &= (ftell(inf)+SnHeaderFrame::SizeOf())<=fend; if (ok) { SnSDUtils::ReadBlockHeader(inf, hcode, hlen); printf("read block hd %02x, len %u\r\n",hcode,hlen); if (hcode==SnHeaderFrame::kPowerCode) { ok &= (ftell(inf)+SnPowerFrame::SizeOf(SnPowerFrame::kIOvers))<=fend; if (ok) { pow.ReadFrom(inf); printf("read power: v1=%g, v2=%g\r\n",pow.GetAveV1(), pow.GetAveV2()); // now read the next header ok &= (ftell(inf)+SnHeaderFrame::SizeOf())<=fend; if (ok) { SnSDUtils::ReadBlockHeader(inf, hcode, hlen); printf("read new header: hc %02x, hlen=%u\r\n",hcode,hlen); } } } } printf(">>> power tried ftell(inf)=%d\r\n",ftell(inf)); printf("hcode=%02x\r\n",hcode); printf("ok=%d\r\n",(int)ok); printf("feof=%d\r\n",feof(inf)); printf("ferror=%d\r\n",ferror(inf)); printf("%d+%u <= %d ? %d\r\n",ftell(inf),hlen,fend, (int)((ftell(inf)+hlen)<=fend)); // TODO: check memory for temporary config/event frames? // get config while ((hcode!=SnHeaderFrame::kConfigCode) && ok && (feof(inf)==0) && (ferror(inf)==0) && ((ftell(inf)+hlen) <= fend) ) { printf("skip: ftell=%d, hlen=%u\r\n",ftell(inf),hlen); fseek(inf, hlen, SEEK_CUR); // skip this block ok = (ftell(inf)+SnHeaderFrame::SizeOf())<=fend; if (ok) { SnSDUtils::ReadBlockHeader(inf, hcode, hlen); printf("hcs >>> ftell(inf)=%d, hcode=%02x, hlen=%u\r\n",ftell(inf),hcode,hlen); printf("feof=%d, ferror=%d\r\n",feof(inf),ferror(inf)); } } printf("checking ftell\r\n"); bool gotConf = false; ok = (ftell(inf)+hlen) <= fend; printf("making temp config\r\n"); SnConfigFrame conf; // TODO: SOMETIMES STALLS HERE! printf("trying to read\r\n"); if (ok && (hcode==SnHeaderFrame::kConfigCode)) { printf("reading config from ftell=%d, hcode=%02x, hlen=%u, ok=%d\r\n", ftell(inf), hcode, hlen, (int)ok); conf.ReadFrom(inf); gotConf = (ftell(inf) <= fend) && (feof(inf)==0) && (ferror(inf)==0); } printf(">>> conf. ftell(inf)=%d, gotconf=%d\r\n",ftell(inf),(int)gotConf); char* b = genBuf; int msiz, mlen; if (ok && gotConf) { // get event size uint8_t sLoseLSB=0, sLoseMSB=0; uint16_t sWvBase=0; curConf.GetPackParsFor(GetCommType(), sLoseLSB, sLoseMSB, sWvBase); // size of event in file const uint32_t esize = SnEventFrame::SizeOf(SnEventFrame::kIOVers, conf.GetWvLoseLSB(), conf.GetWvLoseMSB()); printf("esize=%u\r\n",esize); // number of events / power readings we will send uint32_t evtsSent=0, powsSent=0; b = genBuf; // send the file header SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileHeadrCode, SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers)); SnSDUtils::WriteFileHeader(b, macadr, run, seq); msiz = b-genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); if (mlen==msiz) { // send power header b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, pow.SizeOf(SnPowerFrame::kIOvers)); pow.WriteTo(b); msiz = b-genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ++powsSent; if (mlen==msiz) { // send the config b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kConfigCode, conf.SizeOf(SnConfigFrame::kIOVers)); conf.WriteTo(b); msiz = b-genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); if (mlen==msiz) { ok = true; } } } printf("ok=%d, nevts=%u\r\n",(int)ok,nevts); if (ok) { // size of event sent over afar const uint32_t ssize = SnEventFrame::SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB); // loop over blocks. send event & power frames // until EOF or nevets have been sent uint8_t hc; uint32_t hl; while (ok && (feof(inf)==0) && (ferror(inf)==0) && (ftell(inf)<fend) ) { // feof doesn't seem to work printf(">>> ftell(inf)=%d\r\n",ftell(inf)); if ((ftell(inf)+SnHeaderFrame::SizeOf())<=fend) { SnSDUtils::ReadBlockHeader(inf, hc, hl); if (hc==SnHeaderFrame::kEventCode) { if ((ftell(inf)+ssize)<=fend) { evt.ReadFrom(inf, genBuf, conf.GetWvLoseLSB(), conf.GetWvLoseMSB(), conf.GetWvBaseline()); if (evt.GetEvtNum()>=firstEvt) { ++evtsSent; printf("sending evt %u\r\n",evtsSent); // must be after evt.Read, since that uses the buffer b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kEventCode, ssize); evt.WriteTo(b, sLoseLSB, sLoseMSB, sWvBase); // will repack if necessary msiz = b-genBuf; //SnHeaderFrame::SizeOf()+ssize; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= mlen==msiz; } } else { printf("event header, but not enough bytes in file\r\n"); ok = false; } } else if (hc==SnHeaderFrame::kPowerCode) { if ((ftell(inf)+SnPowerFrame::SizeOf(SnPowerFrame::kIOvers))<=fend) { ++powsSent; pow.ReadFrom(inf); printf("sending power frame %u, v1=%g, v2=%g, t=%u\r\n", powsSent, pow.GetAveV1(), pow.GetAveV2(), pow.GetTime()); b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, SnPowerFrame::SizeOf(SnPowerFrame::kIOvers)); pow.WriteTo(b); msiz = b-genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= mlen==msiz; } else { printf("power header, but not enough bytes in file\r\n"); ok = false; } } else { printf("unhandled block. hc=%hhu, hl=%u\r\n", hc, hl); if ((ftell(inf)+hl)<=fend) { fseek(inf, hl, SEEK_CUR); // skip this block } else { printf("not enough bytes in file to skip block\r\n"); ok = false; } } } else { printf("not enough bytes in file to read header\r\n"); printf("feof=%d\r\n",feof(inf)); printf("ftell(inf)=%d, hdr size=%u, fend=%u\r\n", (ftell(inf)), SnHeaderFrame::SizeOf(), fend); ok = false; } } // send number of events sent b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, sizeof(uint32_t)); b = SnBitUtils::WriteTo(b, evtsSent); msiz = b - genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= msiz==mlen; // send number of power readings sent b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNpwrsCode, sizeof(uint32_t)); b = SnBitUtils::WriteTo(b, powsSent); msiz = b - genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= msiz==mlen; } } else { printf("failed to get config from file\r\n"); // send corrupted file handshake b = genBuf; SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileReadFailCode, 0u); msiz = b-genBuf; mlen = SendAll(genBuf, msiz, timeout_clock); ok &= msiz==mlen; } // put file position back fseek(inf, fpos, SEEK_SET); return ok ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent; } */