Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnCommAfarTCP.cpp

Committer:
uci1
Date:
2012-08-04
Revision:
7:079617408fec
Parent:
6:6f002d202f59
Child:
8:95a325df1f6b

File content as of revision 7:079617408fec:


#include "SnCommAfarTCP.h"

#include "EthernetInterface.h"
#include "TCPSocketConnection.h"

#include "SnSDUtils.h"
#include "SnHeaderFrame.h"
#include "SnConfigFrame.h"
#include "SnEventFrame.h"
#include "SnStatusFrame.h"

#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))

SnCommAfarTCP::SnCommAfarTCP(const bool useb64, const char* remote, const int32_t rport) :
    fUseB64(useb64), fRserv(remote), fRport(rport),
    fEth(new EthernetInterface), fSock(new TCPSocketConnection) {
    
    fEth->init("128.195.204.148",  // my IP
               "255.255.255.0",    // mask
               "128.195.204.1");   // gateway
    
    //fRserv = "128.195.204.151";
    //fRport = 6655;
    
}

SnCommAfarTCP::~SnCommAfarTCP() {
    delete fEth;
    delete fSock;
}

int SnCommAfarTCP::DoIO(char* const data,
                        const uint32_t length,
                        const uint32_t timeout_clock,
                        TCPSendRecv fcn) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
    int res=0;
    uint32_t b=0;
    while ( (length>b) && (time(0)<timeout_clock) ) {
        res = CALL_MEMBER_FN(*fSock, fcn)(data+b, length-b);
        switch (res) {
            case -1:
                // TODO: how to check the error?
                continue;
            case 0:
                return res;
            default:
                b += res;
        };
    }
    return res; // timeout
}

int SnCommAfarTCP::ReceiveAll(char* const buf, const uint32_t mlen,
                              const uint32_t timeout_clock) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
    return DoIO(buf, mlen, timeout_clock, &TCPSocketConnection::receive_all);
}

int SnCommAfarTCP::SendAll(char* const data, const uint32_t length,
                           const uint32_t timeout_clock) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
    return DoIO(data, length, timeout_clock, &TCPSocketConnection::send_all);
}


bool SnCommAfarTCP::Connect(const uint32_t timeout) {
    bool isConn = false;

    while ( (isConn==false) && ( time(0) < timeout) ) {
        wait_ms(250);
        isConn = (fEth->connect()==0);
    }
    
    while ( (isConn==false) && ( time(0) < timeout) ) {
        wait_ms(250);
        isConn = (fSock->connect(fRserv.c_str(), fRport)==0);
    }
    
    return isConn;
}

SnCommWin::ECommWinResult SnCommAfarTCP::OpenWindow(const uint32_t timeout,
                                                    const bool sendStatus,
                                                    const SnConfigFrame& conf,
                                                    const SnEventFrame& evt,
                                                    char* const genBuf) {    
    const bool canCon = Connect(timeout);
    
    SnCommWin::ECommWinResult ret = canCon ? SnCommWin::kConnected
                                           : SnCommWin::kCanNotConnect;
    
    if (canCon && sendStatus) {
        ret = SendStatus(conf, evt, genBuf, timeout);
    }
    
    return ret;
}

SnCommWin::ECommWinResult SnCommAfarTCP::WaitHandshake(const uint32_t timeout,
                                                       char* const buf,
                                                       const uint32_t bsize,
                                                       uint8_t& hndShkCode) {
    printf("WaitHandshake, to=%u\r\n",timeout);
    
    const int mlen = ReceiveAll(buf, SnHeaderFrame::SizeOf(), timeout);
    if (mlen>0 && static_cast<uint32_t>(mlen) == SnHeaderFrame::SizeOf()) {
        uint32_t msgLen=0;
        const char* b = buf;
        SnHeaderFrame::ReadFrom(b, hndShkCode, msgLen);
        if ((hndShkCode & SnHeaderFrame::kHndShkBits)!=0) {
            return SnCommWin::kOkWithMsg;
        } else {
            // TODO: somehow handle unexpected message?
            return SnCommWin::kUnexpectedRec;
        }
    }
    return SnCommWin::kOkNoMsg;
}

SnCommWin::ECommWinResult SnCommAfarTCP::GetConfig(SnConfigFrame& conf,
                                                   const uint32_t timeOut,
                                                   char* const confBuf,
                                                   const uint32_t bsize) {
    // confBuf assumed to alread be of allocated size
    
    printf("GetConfig, to=%u\r\n",timeOut);
    
    SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
    if (bsize<SnHeaderFrame::SizeOf() || bsize<conf.SizeOf()) {
        res = SnCommWin::kUndefFail;
    } else {
        // get header
        const int hlen = ReceiveAll(confBuf, SnHeaderFrame::SizeOf(), timeOut);
        if (hlen>0 && static_cast<uint32_t>(hlen)==SnHeaderFrame::SizeOf()) {
            uint8_t mcode=0; uint32_t mlen=0;
            const char* b = confBuf;
            SnHeaderFrame::ReadFrom(b, mcode, mlen);
            printf("mcode=%02x, mlen=%u\r\n", mcode, mlen);
            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) {
                    b = confBuf;
                    conf.ReadFrom(b);
                    res = SnCommWin::kOkWithMsg;
                } else {
                    res = SnCommWin::kUnexpectedRec;
                }
            }
        } else {
            res = SnCommWin::kUnexpectedRec;
        }
    }
    return res;
}

SnCommWin::ECommWinResult SnCommAfarTCP::SendStatus(const SnConfigFrame& conf,
                                                    const SnEventFrame& evt,
                                                    char* const genBuf,
                                                    const uint32_t timeout_clock) {
    // TODO: check if connected?
    const uint32_t ssize = SnStatusFrame::SizeOf(conf);
    char* b = genBuf;
    SnHeaderFrame::WriteTo(b, SnHeaderFrame::kStatusCode, ssize);
    SnStatusFrame::WriteTo(b, SnConfigFrame::kAfar, conf, evt, genBuf);
#ifdef DEBUG
    printf("status frame:\r\n");
    for (uint32_t i=0; i<msize; i++) {
        printf("%02X ",genBuf[i]);
    }
    printf("\r\n");
#endif
    const int mlen = SendAll(genBuf, b-genBuf, timeout_clock);
    printf("status sent\r\n");
    return (b-genBuf==mlen) ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
}

SnCommWin::ECommWinResult SnCommAfarTCP::SendFilename(const char* fn,
                                                      char* const genBuf,
                                                      const uint32_t timeout_clock) {
    printf("afar send filename %s\r\n",fn);
    const size_t flen = strlen(fn);
    char* b = genBuf;
    SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFilenameCode, flen);
    sprintf(b, "%s", fn);
    const int msiz = SnHeaderFrame::SizeOf()+flen;
    const int mlen = SendAll(genBuf, msiz, timeout_clock);
    return (msiz==mlen) ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
}

SnCommWin::ECommWinResult SnCommAfarTCP::SendFileContents(FILE* inf,
                                                    const SnConfigFrame& curConf,
                                                    SnEventFrame& evt,
                                                    char* const genBuf,
                                                    uint32_t nevts,
                                                    const uint32_t timeout_clock,
                                                    const uint32_t firstEvt) {
    printf("afar send conf and events\r\n");
    // firstEvt==0 ==> start at beginning
    // nevts==0 ==> all events
    
    const int fpos = ftell(inf);
    if (fpos>0) {
        fseek(inf, 0, SEEK_SET);
    }
    
    printf("fpos=%d\r\n",fpos);
    
    // get file header
    uint64_t macadr;
    uint32_t run;
    uint16_t seq, v1, v2;
    SnSDUtils::ReadFileHeader(inf, macadr, run, seq, v1, v2);
    
    // TODO: check memory for temporary config/event frames?
    // get config
    SnConfigFrame conf;
    conf.ReadFrom(inf);
    
    // get event size
    uint8_t sLoseLSB=0, sLoseMSB=0;
    uint16_t sWvBase=0;
    curConf.GetPackParsFor(SnConfigFrame::kAfar, sLoseLSB, sLoseMSB, sWvBase);
    // size of event in file
    const uint32_t esize = SnEventFrame::SizeOf(conf.GetWvLoseLSB(),
                                                conf.GetWvLoseMSB());
    
    printf("esize=%u\r\n",esize);
    
    // how many events?
    // move up to first event
    if (firstEvt>0) {
        printf("skip ahead %d\r\n",firstEvt*esize);
        fseek(inf, (firstEvt*esize), SEEK_CUR);
    }
    // get remaining file size
    const int fcur = ftell(inf);
    fseek(inf, 0, SEEK_END);
    const int fend = ftell(inf);
    fseek(inf, fcur, SEEK_SET);
    const int nevtsLeft = (fend-fcur)/esize; // TODO: check for remainder?
    if (nevts==0 || nevtsLeft<nevts) {
        nevts = nevtsLeft;
    }
    
    // send number of events to expect
    bool ok = false;
    char* b = genBuf;
    SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, nevts);
    int msiz;
    int mlen = SendAll(genBuf, SnHeaderFrame::SizeOf(), timeout_clock);
    if (mlen==SnHeaderFrame::SizeOf()) {
        // send the file header
        b = genBuf;
        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileHeadrCode, SnSDUtils::SizeOfFileHeader());
        SnSDUtils::WriteFileHeader(b, macadr, run, seq, v1, v2);
        msiz = SnHeaderFrame::SizeOf()+SnSDUtils::SizeOfFileHeader();
        mlen = SendAll(genBuf, msiz, timeout_clock);
        if (mlen==msiz) {
            // send the config
            b = genBuf;
            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kConfigCode, conf.SizeOf());
            conf.WriteTo(b);
            msiz = SnHeaderFrame::SizeOf()+conf.SizeOf();
            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(sLoseLSB, sLoseMSB);
        
        for (uint32_t i=0; (i<nevts) && ok; i++) {
            if (feof(inf)==0 && ferror(inf)==0 && ((ftell(inf)+ssize)<=fend)) {
                printf("sending evt %u\r\n",i);
                evt.ReadFrom(inf, genBuf,
                    conf.GetWvLoseLSB(), conf.GetWvLoseMSB(),
                    conf.GetWvBaseline());
                // 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 = SnHeaderFrame::SizeOf()+ssize;
                mlen = SendAll(genBuf, msiz, timeout_clock);
                ok &= mlen==msiz;
            } else {
                printf("cannot send requested event\r\n");
                ok=false;
            }
        }
    }
    
    fseek(inf, fpos, SEEK_SET);
    
    return ok ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
}