From: <bo...@us...> - 2009-11-08 11:51:38
|
Revision: 457 http://gearbox.svn.sourceforge.net/gearbox/?rev=457&view=rev Author: borax00 Date: 2009-11-08 11:51:23 +0000 (Sun, 08 Nov 2009) Log Message: ----------- MR Changes Modified Paths: -------------- gearbox/trunk/doc/history.dox gearbox/trunk/src/gbxgarminacfr/driver.cpp gearbox/trunk/src/gbxgarminacfr/driver.h gearbox/trunk/src/gbxgarminacfr/nmea.cpp gearbox/trunk/src/gbxgarminacfr/nmea.h gearbox/trunk/src/gbxgarminacfr/test/test.cpp gearbox/trunk/src/gbxsickacfr/messages.cpp gearbox/trunk/src/gbxsickacfr/test/test.cpp gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.cpp gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.h gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverhealthchecks.cpp gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverparser.cpp gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.cpp gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.h gearbox/trunk/src/gbxsmartbatteryacfr/test/darttest/checksumtest.cpp gearbox/trunk/src/gbxsmartbatteryacfr/test/longtest.cpp gearbox/trunk/src/gbxutilacfr/exceptions.cpp gearbox/trunk/src/gbxutilacfr/exceptions.h Modified: gearbox/trunk/doc/history.dox =================================================================== --- gearbox/trunk/doc/history.dox 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/doc/history.dox 2009-11-08 11:51:23 UTC (rev 457) @@ -46,6 +46,13 @@ @par Updated libraries +-libGbxSmartBatteryAcfr (tobi) + - improved robustness by encapsulating data of the oceanserversystem class and implementing access/set and check-for-empty functions + - improved healthcheck functions + - bug fix related to initialisation + - improved exception and error handling + - added a raw data record to the oceanserversystem data record useful for debugging + - libflexiport - The UDP port type now properly supports sending and receiving broadcast packets on all operating systems. (GeoffB) @@ -56,7 +63,7 @@ - Thread class: now derives from gbxutilacfr::Stoppable. No changes in user code are requried. (alexm) - Function checkedSleep() is defined in terms of the new light interface class gbxutilacfr::Stoppable. No changes in user code are required. (alexm) - - Implemented store::peek() (Alexb) + - Implemented store::peek() (AlexB) - libGbxUtilAcfr: - Status class: removed SubsystemStalled from the list of health types for a subsystem. The stall condition Modified: gearbox/trunk/src/gbxgarminacfr/driver.cpp =================================================================== --- gearbox/trunk/src/gbxgarminacfr/driver.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxgarminacfr/driver.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -23,16 +23,17 @@ #include "driver.h" using namespace std; -using namespace gbxgarminacfr; /////////////////////////////////////// +namespace gbxgarminacfr { + namespace { // Get the useful bits from a GGA message -GenericData* extractGgaData( gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) +GenericData* extractGgaData( const gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) { - GgaData* data = new GgaData; + std::auto_ptr<GgaData> data( new GgaData ); data->timeStampSec = timeSec; data->timeStampUsec = timeUsec; @@ -58,7 +59,7 @@ data->longitude = 0.0; data->altitude = 0.0; data->geoidalSeparation = 0.0; - return data; + return data.release(); case '1': data->fixType = Autonomous; break; @@ -84,18 +85,20 @@ data->longitude=dir*(deg+(min/60.0)); //altitude - data->altitude=atof(msg.getDataToken(Hgt).c_str()); + data->isAltitudeKnown = !msg.isDataTokenEmpty(Hgt); + if ( data->isAltitudeKnown ) + data->altitude=atof(msg.getDataToken(Hgt).c_str()); //geoidal Separation data->geoidalSeparation=atof(msg.getDataToken(GeoidHgt).c_str()); - return data; + return data.release(); } // VTG provides velocity and heading information -GenericData* extractVtgData( gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) +GenericData* extractVtgData( const gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) { - VtgData* data = new VtgData; + std::auto_ptr<VtgData> data( new VtgData ); data->timeStampSec = timeSec; data->timeStampUsec = timeUsec; @@ -104,15 +107,16 @@ enum VtgTokens{MsgType=0,HeadingTrue,T,HeadingMag,M,SpeedKnots, N,SpeedKPH,K,ModeInd}; - //Check for an empty string. Means that we are not moving - //When the message has empty fields tokeniser skips so we get the next field inline. - if( msg.getDataToken(HeadingTrue)[0] == 'T' ) { - data->headingTrue=0.0; - data->headingMagnetic=0.0; - data->speed=0.0; - // NOTE: not processing the rest! - return data; + //Check for an empty string. Means that we can't tell anything useful. + if ( msg.isDataTokenEmpty(HeadingTrue) ) + { + data->isValid = false; + data->headingTrue = 0.0; + data->headingMagnetic = 0.0; + data->speed = 0.0; + return data.release(); } + data->isValid = true; // true heading double headingRad = DEG2RAD(atof(msg.getDataToken(HeadingTrue).c_str())); @@ -128,16 +132,16 @@ data->speed=atof(msg.getDataToken(SpeedKPH).c_str()); data->speed*=(1000/3600.0); - return data; + return data.release(); } // RME message. This one is garmin specific... Give position error estimates // See doc.dox for a discussion of the position errors as reported here. // Essentially the EPE reported by the garmin is a 1 sigma error (RMS) or a // 68% confidence bounds. -GenericData* extractRmeData( gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) +GenericData* extractRmeData( const gbxgpsutilacfr::NmeaMessage& msg, int timeSec, int timeUsec ) { - RmeData* data = new RmeData; + std::auto_ptr<RmeData> data( new RmeData ); data->timeStampSec = timeSec; data->timeStampUsec = timeUsec; @@ -145,11 +149,33 @@ //Names for the RME message items enum RmeTokens{MsgType=0,HError,M1,VError,M2,EPE,M3}; + if ( msg.isDataTokenEmpty(HError) ) + { + // No valid information + data->isValid = false; + data->isVerticalPositionErrorValid = false; + data->horizontalPositionError = 0.0; + data->verticalPositionError = 0.0; + data->estimatedPositionError = 0.0; + return data.release(); + } + data->isValid = true; + data->horizontalPositionError = atof(msg.getDataToken(HError).c_str()); - data->verticalPositionError = atof(msg.getDataToken(VError).c_str()); + if ( msg.isDataTokenEmpty(VError) ) + { + data->isVerticalPositionErrorValid = false; + data->verticalPositionError = -1; + } + else + { + data->isVerticalPositionErrorValid = true; + data->verticalPositionError = atof(msg.getDataToken(VError).c_str()); + } + data->estimatedPositionError = atof(msg.getDataToken(EPE).c_str()); - return data; + return data.release(); } } @@ -172,9 +198,9 @@ Config::toString() const { std::stringstream ss; - ss << "Garmin driver config: " << - "\tdevice="<<device << - "\twill read sentences: GPGGA="<<readGga<<" GPVTG="<<readVtg<<" PGRME="<<readRme; + ss << "Garmin driver config: " << endl + << "\tdevice="<<device << endl + << "\twill read sentences: GPGGA="<<readGga<<" GPVTG="<<readVtg<<" PGRME="<<readRme; return ss.str(); } @@ -209,7 +235,15 @@ Driver::~Driver() { - disableDevice(); + // Don't throw from destructors... + try { + disableDevice(); + } + catch ( const std::exception &e ) + { + cout << "Driver::~Driver: exception while disabling: " << e.what() << endl; + } + catch ( ... ) {} } void @@ -240,6 +274,7 @@ gbxgpsutilacfr::NmeaMessage disableAllMsg( "$PGRMO,,2*xx\r\n",gbxgpsutilacfr::AddChecksum ); serial_->writeString( disableAllMsg.sentence() ); + // alexb: what is this sleep for? sleep(1); if ( config_.readGga ) { @@ -247,7 +282,6 @@ serial_->writeString( enableGgaMsg.sentence() ); } - if ( config_.readVtg ) { gbxgpsutilacfr::NmeaMessage enableVtgMsg( "$PGRMO,GPVTG,1*xx\r\n",gbxgpsutilacfr::AddChecksum ); serial_->writeString( enableVtgMsg.sentence() ); @@ -258,6 +292,7 @@ serial_->writeString( enableRmeMsg.sentence() ); } + // alexb: what is this sleep for? sleep(1); } @@ -273,11 +308,7 @@ Driver::read() { std::auto_ptr<GenericData> genericData; - gbxgpsutilacfr::NmeaMessage nmeaMessage; - // Make sure that we clear our internal data structures - // alexm: is this necessary? should NmeaMessage do it for itself? - memset((void*)(&nmeaMessage) , 0 , sizeof(nmeaMessage)); int nmeaExceptionCount = 0; int nmeaFailChecksumCount = 0; @@ -330,7 +361,7 @@ //Put it into the message object and checksum the data try { // This throws if it cannot find the * to deliminate the checksum field - nmeaMessage.setSentence( serialData.c_str(), gbxgpsutilacfr::TestChecksum ); + nmeaMessage.setSentence( serialData, gbxgpsutilacfr::TestChecksum ); } catch ( const gbxgpsutilacfr::NmeaException& e ) { //Don't throw on isolated checksum problems @@ -384,7 +415,10 @@ else throw gbxutilacfr::Exception( ERROR_INFO, "got unexpected GPGGA message" ); genericData.reset( extractGgaData( nmeaMessage, now.tv_sec, now.tv_usec ) ); - break; + if ( genericData.get() ) + break; + else + continue; } else if ( MsgType == "$GPVTG" ) { if ( config_.readVtg ) @@ -392,7 +426,10 @@ else throw gbxutilacfr::Exception( ERROR_INFO, "got unexpected GPVTG message" ); genericData.reset( extractVtgData( nmeaMessage, now.tv_sec, now.tv_usec ) ); - break; + if ( genericData.get() ) + break; + else + continue; } else if ( MsgType == "$PGRME" ) { if ( config_.readRme ) @@ -400,7 +437,10 @@ else throw gbxutilacfr::Exception( ERROR_INFO, "got unexpected PGRME message" ); genericData.reset( extractRmeData( nmeaMessage, now.tv_sec, now.tv_usec ) ); - break; + if ( genericData.get() ) + break; + else + continue; } else if ( MsgType == "$PGRMO" ) { //This message is sent by us to control msg transmission and then echoed by GPS @@ -415,8 +455,64 @@ else throw gbxutilacfr::Exception( ERROR_INFO, ss.str() ); } + } + return genericData; +} +std::string toString( const FixType &f ) +{ + switch ( f ) + { + case Invalid: return "Invalid"; + case Autonomous: return "Autonomous"; + case Differential: return "Differential"; + default: return "??"; } +} - return genericData; +std::string toString( const GgaData &d ) +{ + stringstream ss; + ss << endl; + ss << " timeStampSec : " << d.timeStampSec << endl + << " timeStampUsec : " << d.timeStampUsec << endl + << " utcTimeHrs : " << d.utcTimeHrs << endl + << " utcTimeMin : " << d.utcTimeMin << endl + << " utcTimeSec : " << d.utcTimeSec << endl + << " latitude : " << d.latitude << endl + << " longitude : " << d.longitude << endl + << " isAltitudeKnown : " << d.isAltitudeKnown << endl + << " altitude : " << d.altitude << endl + << " fixType : " << d.fixType << endl + << " satellites : " << d.satellites << endl + << " horizontalDilutionOfPosition : " << d.horizontalDilutionOfPosition << endl + << " geoidalSeparation : " << d.geoidalSeparation; + return ss.str(); } +std::string toString( const VtgData &d ) +{ + stringstream ss; + ss << endl; + ss << " timeStampSec : " << d.timeStampSec << endl + << " timeStampUsec : " << d.timeStampUsec << endl + << " isValid : " << d.isValid << endl + << " headingTrue : " << d.headingTrue << endl + << " headingMagnetic : " << d.headingMagnetic << endl + << " speed : " << d.speed; + return ss.str(); +} +std::string toString( const RmeData &d ) +{ + stringstream ss; + ss << endl; + ss << " timeStampSec : " << d.timeStampSec << endl + << " timeStampUsec : " << d.timeStampUsec << endl + << " isValid : " << d.isValid << endl + << " horizontalPositionError : " << d.horizontalPositionError << endl + << " isVerticalPositionErrorValid : " << d.isVerticalPositionErrorValid << endl + << " verticalPositionError : " << d.verticalPositionError << endl + << " estimatedPositionError : " << d.estimatedPositionError; + return ss.str(); +} + +} Modified: gearbox/trunk/src/gbxgarminacfr/driver.h =================================================================== --- gearbox/trunk/src/gbxgarminacfr/driver.h 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxgarminacfr/driver.h 2009-11-08 11:51:23 UTC (rev 457) @@ -85,6 +85,7 @@ //! Differentially corrected Differential }; +std::string toString( const FixType &f ); //! Fix data structure. Note that when fixType is Invalid, all other data except the time stamps //! are meaningless. @@ -114,7 +115,9 @@ double latitude; //! Longitude [degrees] double longitude; - //! Altitude [metres above ellipsoid] + //! Altitude is meaningful if and only if isAltitudeKnown + bool isAltitudeKnown; + //! Altitude [metres above ellipsoid] (only meaningful if isAltitudeKnown) double altitude; //! Fix type. When fixType is Invalid, all other data except the time stamps @@ -130,6 +133,9 @@ //! Height of geoid (mean sea level) above WGS84 ellipsoid [metres] double geoidalSeparation; }; +std::string toString( const GgaData &d ); +inline std::ostream &operator<<( std::ostream &s, const GgaData &d ) +{ return s << toString(d); } //! Vector track and speed over ground data structure. class VtgData : public GenericData @@ -143,6 +149,10 @@ //! Time (according to the computer clock) when data was measured. //! Number of microseconds int timeStampUsec; + + //! When false, means that the GPS unit can't make a valid measurement + //! (so all data other than the timestamp is meaningless). + bool isValid; //! Heading/track/course with respect to true North [rad] double headingTrue; @@ -151,6 +161,9 @@ //! Horizontal velocity [metres/second] double speed; }; +std::string toString( const VtgData &d ); +inline std::ostream &operator<<( std::ostream &s, const VtgData &d ) +{ return s << toString(d); } //! Gps data structure class RmeData : public GenericData @@ -165,6 +178,14 @@ //! Number of microseconds int timeStampUsec; + //! When false, means that the GPS unit can't make a valid measurement + //! (so all data other than the timestamp is meaningless). + bool isValid; + + //! When false, means that the GPS unit can't tell us anything + //! about our vertical error + bool isVerticalPositionErrorValid; + //! Horizontal position error: one standard deviation [metres)] double horizontalPositionError; //! Vertical position error: one standard deviation [metres] @@ -173,6 +194,9 @@ //! Estimated position error. double estimatedPositionError; }; +std::string toString( const RmeData &d ); +inline std::ostream &operator<<( std::ostream &s, const RmeData &d ) +{ return s << toString(d); } /*! Garmin GPS driver. Modified: gearbox/trunk/src/gbxgarminacfr/nmea.cpp =================================================================== --- gearbox/trunk/src/gbxgarminacfr/nmea.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxgarminacfr/nmea.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -12,33 +12,34 @@ #include <string> #include <iostream> #include <assert.h> +#include <sstream> #include <gbxutilacfr/tokenise.h> -////////////////////////////// +// ////////////////////////////// -// Ensure we have strnlen -// eg. Solaris doesn't define strnlen in string.h, so define it here. -#if !HAVE_STRNLEN +// // Ensure we have strnlen +// // eg. Solaris doesn't define strnlen in string.h, so define it here. +// #if !HAVE_STRNLEN -#include <cstring> +// #include <cstring> -// inline the fucker to guard against multiple inclusion, without the -// hassle of a special lib. -inline size_t strnlen(const char *s, size_t maxlen) -{ - char *p; - if (s == NULL) { - return maxlen; - } - p = (char *)memchr(s, 0, maxlen); - if (p == NULL) { - return maxlen; - } - return ((p - s) + 1); -} -#endif +// // inline the fucker to guard against multiple inclusion, without the +// // hassle of a special lib. +// inline size_t strnlen(const char *s, size_t maxlen) +// { +// char *p; +// if (s == NULL) { +// return maxlen; +// } +// p = (char *)memchr(s, 0, maxlen); +// if (p == NULL) { +// return maxlen; +// } +// return ((p - s) + 1); +// } +// #endif -////////////////////////////// +// ////////////////////////////// #include "nmea.h" @@ -57,39 +58,30 @@ void NmeaMessage::init() { - haveSentence_ = false; - haveTokens_ = false; haveCheckSum_ = false; checkSumOK_ = false; // Now clear the internal data store - sentence_[0] = 0; + sentence_.clear(); dataTokens_.clear(); } - -NmeaMessage::NmeaMessage(const char *sentence, int testCheckSum) +NmeaMessage::NmeaMessage(const std::string &sentence, NmeaMessageOptions addOrTestCheckSum) { init(); - setSentence(sentence,testCheckSum); + setSentence(sentence,addOrTestCheckSum); } //Load the data as requested and test the checksum if we are asked to. void -NmeaMessage::setSentence(const char *data, int AddOrTestCheckSum) +NmeaMessage::setSentence(const std::string &data, NmeaMessageOptions addOrTestCheckSum) { init(); - - strncpy(sentence_,data, MAX_SENTENCE_LEN); - //terminate just in case, Note that we have a buffer which is - //MAX_SENTENCE_LEN + 1 long! - - sentence_[MAX_SENTENCE_LEN] = '\0'; - haveSentence_ = true; + sentence_ = data; - switch ( AddOrTestCheckSum ) + switch ( addOrTestCheckSum ) { case TestChecksum: { // This is for Rx'd data that we need to test for correct reception @@ -106,7 +98,7 @@ case DontTestOrAddChecksum: break; default: - assert( true && "unrecognized message option" ); + assert( false && "unrecognized message option" ); } } @@ -116,34 +108,36 @@ haveCheckSum_ = true; checkSumOK_ = false; - //First save the checksum chars from the existing message - char* ptr; - char chksum_HIB,chksum_LOB; - //First save the existing two checksum chars from the message //These are straight after the '*' character - ptr = strchr(sentence_, NMEAChecksumDelim); - if ( !ptr ) { -// cout<<"device: no checksum delimiter"<<endl; + const size_t starPos = sentence_.find( NMEAChecksumDelim ); + if ( starPos == std::string::npos ) + { + // cout<<"device: no checksum delimiter"<<endl; return false; } + + if ( starPos+2 >= sentence_.size() ) + { + // cout<<"device: no checksum after delimiter"<<endl; + return false; + } //save the high and low bytes of the checksum //Make sure they are in upper case! - chksum_HIB = (char)toupper(*(++ptr)); - chksum_LOB = (char)toupper(*(ptr + 1)); - + const int checksumPos = starPos+1; + const char chksum_HIB = (char)toupper(sentence_[checksumPos]); + const char chksum_LOB = (char)toupper(sentence_[checksumPos+1]); //invalidate the existing checksum - *ptr = *(ptr+1) = 'x'; - - //****NOTE** We leave the ptr pointing at the first chksum byte - + sentence_[checksumPos] = 'x'; + sentence_[checksumPos+1] = 'x'; + //Re-calculate our own copy of the checksum addCheckSum(); //Now compare our saved version with our new ones - if( (chksum_HIB == *ptr) && (chksum_LOB == *(ptr+1)) ) { + if( (chksum_HIB == sentence_[checksumPos]) && (chksum_LOB == sentence_[checksumPos+1]) ) { //all looked good! checkSumOK_ = true; return true; @@ -160,9 +154,9 @@ // the checksum, and that the checksum delimiter is there void NmeaMessage::addCheckSum() -{ - assert( haveSentence_ && "calling addCheckSum() without a sentence" ); - +{ + assert( haveSentence() && "calling addCheckSum() without a sentence" ); + haveCheckSum_ = true; //check that we have the '$' at the start @@ -172,12 +166,11 @@ unsigned char chkRunning = 0; + // we start from 1 to skip the leading '$' int loopCount; - unsigned char nextChar; - // we start from 1 to skip the leading '$' - for( loopCount=1; loopCount<MAX_SENTENCE_LEN; ++loopCount ) + for ( loopCount = 1; loopCount < (int)(sentence_.size()); loopCount++ ) { - nextChar = static_cast<unsigned char>(sentence_[loopCount]); + unsigned char nextChar = static_cast<unsigned char>(sentence_[loopCount]); // no delimiter uh oh if( (nextChar=='\r') || (nextChar=='\n') || (nextChar=='\0') ) { @@ -196,9 +189,14 @@ // Keep the running XOR total chkRunning ^= nextChar; } + + if ( loopCount+2 >= (int)(sentence_.size()) ) + { + throw NmeaException("addCheckSum(): no space for checksum of '*' not found."); + } //Put the byte values as upper case HEX back into the message - sprintf( sentence_ + loopCount + 1,"%02X", chkRunning ); + sprintf( &(sentence_[loopCount + 1]),"%02X", chkRunning ); } // Parse the data fields of our message... @@ -218,3 +216,39 @@ //keep track of what we have done. haveTokens_ = true; } + +bool +NmeaMessage::isDataTokenEmpty(int i) const +{ + if ( i >= (int)(dataTokens_.size()) ) + { + stringstream ss; + ss << "NmeaMessage::" << __func__ + << ": attempt to getDataToken("<<i<<") but only " << dataTokens_.size() << " exist in sentence: " + << sentence_; + throw NmeaException( ss.str() ); + } + return dataTokens_[i].empty(); +} + +const std::string & +NmeaMessage::getDataToken(int i) const +{ + if ( i >= (int)(dataTokens_.size()) ) + { + stringstream ss; + ss << "NmeaMessage::" << __func__ + << ": attempt to getDataToken("<<i<<") but only " << dataTokens_.size() << " exist in sentence: " + << sentence_; + throw NmeaException( ss.str() ); + } + if ( dataTokens_[i].empty() ) + { + stringstream ss; + ss << "NmeaMessage::" << __func__ + << ": attempt to getDataToken("<<i<<") but this token is empty in sentence: " + << sentence_; + throw NmeaException( ss.str() ); + } + return dataTokens_[i]; +} Modified: gearbox/trunk/src/gbxgarminacfr/nmea.h =================================================================== --- gearbox/trunk/src/gbxgarminacfr/nmea.h 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxgarminacfr/nmea.h 2009-11-08 11:51:23 UTC (rev 457) @@ -78,14 +78,14 @@ { public: NmeaMessage(); - NmeaMessage(const char *sentence, int testCheckSum=DontTestOrAddChecksum ); + NmeaMessage(const std::string &sentence, NmeaMessageOptions addOrTestCheckSum=DontTestOrAddChecksum ); // Set up the internal data for a sentence. // May throw NmeaException if TestChecksum is specified. - void setSentence(const char *data, int testCheckSum=DontTestOrAddChecksum ); + void setSentence(const std::string &data, NmeaMessageOptions addOrTestCheckSum=DontTestOrAddChecksum ); - // Do we only have the raw string? - bool haveSentence() const { return haveSentence_; }; + // Do we have the raw string? + bool haveSentence() const { return !sentence_.empty(); }; // Do we have parsed fields? bool haveTokens() const { return haveTokens_; }; @@ -101,11 +101,14 @@ bool testChecksumOk(); // Return the raw sentence string - const char* sentence() { return sentence_; }; + const std::string &sentence() const { return sentence_; }; - // Return a single data token as a string - std::string& getDataToken(int i) { return dataTokens_[i]; }; + // Return a single data token as a string. + // Throws an exception if that token is empty (see 'isDataTokenEmpty()') + const std::string &getDataToken(int i) const; + bool isDataTokenEmpty(int i) const; + // Return the number of fields int numDataTokens() const { return dataTokens_.size(); }; @@ -116,15 +119,14 @@ void init(); // May throw NmeaException. void addCheckSum(); - // Do we only have the raw string ? - bool haveSentence_; // Have we parsed data into tokens ? bool haveTokens_; // Have we a checksum and is it valid? bool haveCheckSum_; bool checkSumOK_; // The raw sentence, allow for terminator - char sentence_[MAX_SENTENCE_LEN+1]; +// char sentence_[MAX_SENTENCE_LEN+1]; + std::string sentence_; // The tokenised data std::vector<std::string> dataTokens_; }; Modified: gearbox/trunk/src/gbxgarminacfr/test/test.cpp =================================================================== --- gearbox/trunk/src/gbxgarminacfr/test/test.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxgarminacfr/test/test.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -32,22 +32,31 @@ // defaults string port = "/dev/ttyS0"; bool quiet = false; + int numReads = 30; + int debugLevel = 5; // Get some options from the command line - while ((opt = getopt(argc, argv, "p:q")) != -1) + while ((opt = getopt(argc, argv, "p:n:d:q")) != -1) { switch ( opt ) { case 'p': port = optarg; break; + case 'n': + numReads=atoi(optarg); + break; + case 'd': + debugLevel=atoi(optarg); + break; case 'q': quiet = true; break; default: cout << "Usage: " << argv[0] << " [-p port]" << endl << endl - << "-p port\tPort the device is connected to. E.g. /dev/ttyS0" - << "-q \tMakes normal operation quiet, only errors are traced." << endl; + << "-p port \tPort the device is connected to. E.g. /dev/ttyS0" << endl + << "-n numReads\tNumber of times to read from the device" << endl + << "-q \tMakes normal operation quiet, only errors are traced." << endl; return 1; } } @@ -66,17 +75,16 @@ cout << "Using configuration: " << config.toString() << endl; // Instantiate objects to handle messages from the driver - bool debug = 5; if ( quiet ) - debug = 0; - gbxutilacfr::TrivialTracer tracer( debug ); + debugLevel = 0; + gbxutilacfr::TrivialTracer tracer( debugLevel ); gbxutilacfr::TrivialStatus status( tracer ); // Instantiate the driver itself - gbxgarminacfr::Driver* device; + std::auto_ptr<gbxgarminacfr::Driver> device; try { - device = new gbxgarminacfr::Driver( config, tracer, status ); + device.reset( new gbxgarminacfr::Driver( config, tracer, status ) ); } catch ( const std::exception& e ) { @@ -88,7 +96,6 @@ std::auto_ptr<gbxgarminacfr::GenericData> data; // Read a few times - const int numReads = 30 + 10000000; for ( int i=0; i < numReads; i++ ) { try @@ -142,7 +149,5 @@ cout <<"Test: Failed to read data: "<<e.what()<<endl; } } - - delete device; return 0; } Modified: gearbox/trunk/src/gbxsickacfr/messages.cpp =================================================================== --- gearbox/trunk/src/gbxsickacfr/messages.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsickacfr/messages.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -893,6 +893,7 @@ if ( checksumFailed ) { IceUtil::Time t = IceUtil::Time::now(); + cout << "========== Checksum failed, timestamp: " << t.toDateTime() << endl; // cout << "WARN(messages.cpp): " << t.toDateTime() << ": Checksum failed at buf pos " <<bytesParsed << endl; // cout<<"TRACE(messages.cpp): checksum was over: " << toHexString( &(buffer[bytesParsed]), telegramLength ) << endl; bytesParsed++; Modified: gearbox/trunk/src/gbxsickacfr/test/test.cpp =================================================================== --- gearbox/trunk/src/gbxsickacfr/test/test.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsickacfr/test/test.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -12,7 +12,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <iostream> #include <sstream> @@ -28,30 +27,35 @@ // int main( int argc, char **argv ) { - int opt; int baud = 38400; string port = "/dev/ttyS0"; int debug = 0; bool showScan = false; // Get some options from the command line - while ((opt = getopt(argc, argv, "p:b:vs")) != -1) + for ( int i=1; i < argc; i++ ) { - switch ( opt ) + if ( !strcmp(argv[i],"-p") && i < argc-1 ) { - case 'p': - port = optarg; - break; - case 'b': - baud = atoi( optarg ); - break; - case 'v': - debug = 5; - break; - case 's': + port = argv[i+1]; + i++; + } + else if ( !strcmp(argv[i],"-b") && i < argc-1 ) + { + baud = atoi(argv[i+1]); + i++; + } + else if ( !strcmp(argv[i],"-v") ) + { + debug = true; + } + else if ( !strcmp(argv[i],"-s") ) + { showScan = true; - break; - default: + } + else + { + cout << "Unknown option: " << argv[i] << endl; cout << "Usage: " << argv[0] << " [-p port] [-b baud] [-v(erbose)] [-s(how scan)]" << endl << endl << "-p port\tPort the laser scanner is connected to. E.g. /dev/ttyS0" << endl << "-b baud\tBaud rate to connect at (9600, 19200, 38400, or 500000)." << endl; Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -36,7 +36,7 @@ // read new data, this may throw reader_->read(data); - // if successful, reset counter and string + // successful read: reset counter and string exceptionCounter_ = 0; exceptionString_ = ""; @@ -54,8 +54,8 @@ exceptionCounter_++; stringstream ssEx; ssEx << e.what() << endl; - for (unsigned int i=0; i<data.rawRecord.size(); i++) - ssEx << data.rawRecord[i] << endl; + for (unsigned int i=0; i<data.rawRecord().size(); i++) + ssEx << data.rawRecord()[i] << endl; ssEx << endl; exceptionString_ = exceptionString_ + ssEx.str(); @@ -79,7 +79,8 @@ } // return updated internal storage - // if there was an exception on read, we just return the previous record + // if there was an exception on read which does not get re-thrown above, + // the internal storage will contain the previous record return data_; } Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.h =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.h 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserver.h 2009-11-08 11:51:23 UTC (rev 457) @@ -38,6 +38,7 @@ //! Reads data from OceanServer, incrementally updates internal storage //! Returns a reference to the internal storage //! May throw gbxutilacfr::Exception + //! May return an empty record ( check with isEmpty() ) const gbxsmartbatteryacfr::OceanServerSystem& getData(); private: Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverhealthchecks.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverhealthchecks.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverhealthchecks.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -18,12 +18,24 @@ { namespace { - + + bool isRecordEmpty( const OceanServerSystem &batteryData, + vector<string> &warnShort, + vector<string> &warnVerbose) + { + if ( !batteryData.isEmpty() ) + return false; + + warnVerbose.push_back("The OceanServerSystem data record was empty"); + warnShort.push_back("EMPTY RECORD"); + return true; + } + bool haveBattery( const OceanServerSystem &batteryData, vector<string> &warnShort, vector<string> &warnVerbose ) { - const vector<bool> &bats = batteryData.availableBatteries; + const vector<bool> &bats = batteryData.availableBatteries(); bool haveBattery = false; for (unsigned int i=0; i<bats.size(); i++) { @@ -58,10 +70,12 @@ std::vector<std::string> &warnVerbose, int expectedNumBatteries ) { + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; + bool haveWarning = false; int numBatteries = 0; - const vector<bool> &bats = batteryData.availableBatteries; + const vector<bool> &bats = batteryData.availableBatteries(); for (unsigned int i=0; i<bats.size(); i++) { @@ -72,10 +86,10 @@ if ( numBatteries!=expectedNumBatteries ) { stringstream ssWarnShort; - ssWarnShort << "ONLY " << numBatteries << " BATTERIES! "; + ssWarnShort << "HAVE " << numBatteries << ", EXP " << expectedNumBatteries << " BAT! "; warnShort.push_back(ssWarnShort.str()); stringstream ssWarnVerbose; - ssWarnVerbose << "Only found " << numBatteries << " battery modules (expected to see " << expectedNumBatteries << ")" << endl; + ssWarnVerbose << "Found " << numBatteries << " battery modules (expected to see " << expectedNumBatteries << ")" << endl; warnVerbose.push_back( ssWarnVerbose.str() ); haveWarning = true; } @@ -89,6 +103,8 @@ int numCyclesThreshhold, bool printRawRecord ) { + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; + bool haveWarning = false; map<int,SmartBattery>::const_iterator it; @@ -114,7 +130,7 @@ if (haveWarning && printRawRecord) { stringstream ssWarnVerbose; - ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord) << endl; + ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord()) << endl; warnVerbose.push_back(ssWarnVerbose.str()); } @@ -128,7 +144,9 @@ double chargeTempThreshhold, double dischargeTempThreshhold, bool printRawRecord ) -{ +{ + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; + bool haveWarning = false; map<int,SmartBattery>::const_iterator it; @@ -139,8 +157,8 @@ const SmartBattery &bat = batteryData.battery( batteryNumber ); if ( !bat.has(Temperature) ) continue; - assert( (int)batteryData.chargingStates.size() >= batteryNumber-1 ); - bool isCharging = batteryData.chargingStates[batteryNumber-1]; + assert( (int)batteryData.chargingStates().size() >= batteryNumber-1 ); + bool isCharging = batteryData.chargingStates()[batteryNumber-1]; double tempThreshhold = 0.0; if (isCharging) { @@ -165,7 +183,7 @@ if (haveWarning && printRawRecord) { stringstream ssWarnVerbose; - ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord) << endl; + ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord()) << endl; warnVerbose.push_back(ssWarnVerbose.str()); } @@ -178,6 +196,12 @@ int chargeWarnThreshhold, int chargeDeviationThreshold ) { + + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; + + // if the system is charging, don't bother issuing warnings + if ( isSystemOnCharge(batteryData) ) return false; + bool haveWarning = false; map<int,SmartBattery>::const_iterator it; @@ -189,7 +213,7 @@ if ( !bat.has(RelativeStateOfCharge) ) continue; int charge = bat.relativeStateOfCharge(); - const int avgCharge = batteryData.percentCharge; + const int avgCharge = batteryData.percentCharge(); // check whether battery charge is lower than the average if ( charge < (avgCharge - chargeDeviationThreshold) ) @@ -202,8 +226,7 @@ ssWarnVerbose << "Inconsistent charge! Battery no " << batteryNumber << "'s charge is " << charge << "% (average: " << avgCharge << "%)" << endl; warnVerbose.push_back(ssWarnVerbose.str()); } - - // check whether battery charge is below a threshhold + if (charge < chargeWarnThreshhold) { haveWarning = true; @@ -219,14 +242,17 @@ return haveWarning; } -bool checkModuleHealth( const OceanServerSystem &batteryData, +bool checkModuleHealth( const OceanServerSystem &batteryData, vector<string> &warnShort, vector<string> &warnVerbose ) { + + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; + bool haveWarning = false; // check the flags - const vector<bool> &badPower = batteryData.powerNoGoodStates; + const vector<bool> &badPower = batteryData.powerNoGoodStates(); for (unsigned int i=0; i<badPower.size(); i++) { if (badPower[i]==true) @@ -241,7 +267,7 @@ } } - const vector<bool> &chargeInhibit = batteryData.chargeInhibitedStates; + const vector<bool> &chargeInhibit = batteryData.chargeInhibitedStates(); for (unsigned int i=0; i<chargeInhibit.size(); i++) { if (chargeInhibit[i]==true) @@ -265,20 +291,29 @@ std::vector<std::string> &warnVerbose, bool printRawRecord ) { - if ( !haveBattery( batteryData, warnShort, warnVerbose ) ) return true; + if ( isRecordEmpty(batteryData, warnShort, warnVerbose) ) return true; - bool warnNumBatteries = checkNumberOfBatteries( batteryData, warnShort, warnVerbose, batteryConfig.expectedNumBatteries ); - bool warnModule = checkModuleHealth( batteryData, warnShort, warnVerbose ); - bool warnCycle = checkNumCycles( batteryData, warnShort, warnVerbose, batteryConfig.numCyclesThreshhold, false ); - bool warnTemp = checkTemperatures( batteryData, warnShort, warnVerbose, batteryConfig.chargeTempThreshhold, batteryConfig.dischargeTempThreshhold, false ); - bool warnCharge = checkCharges( batteryData, warnShort, warnVerbose, batteryConfig.chargeWarnThreshhold, batteryConfig.chargeDeviationThreshold ); + bool haveWarnings = false; + + if ( haveBattery( batteryData, warnShort, warnVerbose ) ) + { + bool warnNumBatteries = checkNumberOfBatteries( batteryData, warnShort, warnVerbose, batteryConfig.expectedNumBatteries ); + bool warnModule = checkModuleHealth( batteryData, warnShort, warnVerbose ); + bool warnCycle = checkNumCycles( batteryData, warnShort, warnVerbose, batteryConfig.numCyclesThreshhold, false ); + bool warnTemp = checkTemperatures( batteryData, warnShort, warnVerbose, batteryConfig.chargeTempThreshhold, batteryConfig.dischargeTempThreshhold, false ); + bool warnCharge = checkCharges( batteryData, warnShort, warnVerbose, batteryConfig.chargeWarnThreshhold, batteryConfig.chargeDeviationThreshold ); + + haveWarnings = warnNumBatteries || warnModule || warnCycle || warnTemp || warnCharge; + } + else + { + haveWarnings = true; + } - bool haveWarnings = warnNumBatteries || warnModule || warnCycle || warnTemp || warnCharge; - if (printRawRecord && haveWarnings ) { stringstream ssWarnVerbose; - ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord) << endl; + ssWarnVerbose << "Latest raw record: " << endl << toString(batteryData.rawRecord()) << endl; warnVerbose.push_back(ssWarnVerbose.str()); } Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverparser.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverparser.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserverparser.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -34,16 +34,16 @@ for (it=keyValuePairs.begin(); it!=keyValuePairs.end(); it++) { if (it->first=="01") { - batterySystem.minToEmpty = readMinutes(it->second); + batterySystem.setMinToEmpty( readMinutes(it->second) ); } else if (it->first=="02") { // reserved, do nothing } else if (it->first=="03") { - batterySystem.messageToSystem = it->second; + batterySystem.setMessageToSystem( it->second ); } else if (it->first=="04") { - batterySystem.percentCharge = readPercentByte(it->second); + batterySystem.setPercentCharge( readPercentByte(it->second) ); } else { @@ -66,30 +66,30 @@ if (it->first=="01") { readFlags(it->second, states); - batterySystem.availableBatteries = states; + batterySystem.availableBatteries() = states; } else if (it->first=="02") { readFlags(it->second, states); - batterySystem.chargingStates = states; + batterySystem.chargingStates() = states; } else if (it->first=="03") { readFlags(it->second, states); - batterySystem.supplyingPowerStates = states; + batterySystem.supplyingPowerStates() = states; } else if (it->first=="04") { // reserved, do nothing } else if (it->first=="05") { readFlags(it->second, states); - batterySystem.chargePowerPresentStates = states; + batterySystem.chargePowerPresentStates() = states; } else if (it->first=="06") { readFlags(it->second, states); - batterySystem.powerNoGoodStates = states; + batterySystem.powerNoGoodStates() = states; } else if (it->first=="07") { readFlags(it->second, states); - batterySystem.chargeInhibitedStates = states; + batterySystem.chargeInhibitedStates() = states; } else { @@ -254,7 +254,7 @@ { // put the raw record into the batterySystem representation // useful for "higher-level" debugging: the caller can choose how to make use of this information - batterySystem.rawRecord = stringList; + batterySystem.rawRecord() = stringList; // // Debugging output Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -49,17 +49,18 @@ // // Non-member functions // + string toString( const OceanServerSystem &system ) { stringstream ss; - ss << "Charge: \t" << system.percentCharge << endl; - ss << "Minutes to empty:\t" << system.minToEmpty << endl; - ss << "Available batt.: \t" << toString( system.availableBatteries ) << endl; - ss << "Charging: \t" << toString( system.chargingStates ) << endl; - ss << "Supplying power: \t" << toString( system.supplyingPowerStates ) << endl; - ss << "Charge power: \t" << toString( system.chargePowerPresentStates ) << endl; - ss << "Power no good: \t" << toString( system.powerNoGoodStates ) << endl; - ss << "Charge inhibited:\t" << toString( system.chargeInhibitedStates ) << endl; + ss << "Charge: \t" << system.percentCharge() << endl; + ss << "Minutes to empty:\t" << system.minToEmpty() << endl; + ss << "Available batt.: \t" << toString( system.availableBatteries() ) << endl; + ss << "Charging: \t" << toString( system.chargingStates() ) << endl; + ss << "Supplying power: \t" << toString( system.supplyingPowerStates() ) << endl; + ss << "Charge power: \t" << toString( system.chargePowerPresentStates() ) << endl; + ss << "Power no good: \t" << toString( system.powerNoGoodStates() ) << endl; + ss << "Charge inhibited:\t" << toString( system.chargeInhibitedStates() ) << endl; map<int,SmartBattery>::const_iterator it; for (it=system.batteries().begin(); it!=system.batteries().end(); it++) @@ -74,14 +75,14 @@ string toLogString( const OceanServerSystem &system ) { stringstream ss; - ss << system.percentCharge << " "; - ss << system.minToEmpty << " "; - ss << toLogString( system.availableBatteries ) << " "; - ss << toLogString( system.chargingStates ) << " "; - ss << toLogString( system.supplyingPowerStates ) << " "; - ss << toLogString( system.chargePowerPresentStates ) << " "; - ss << toLogString( system.powerNoGoodStates ) << " "; - ss << toLogString( system.chargeInhibitedStates ) << endl; + ss << system.percentCharge() << " "; + ss << system.minToEmpty() << " "; + ss << toLogString( system.availableBatteries() ) << " "; + ss << toLogString( system.chargingStates() ) << " "; + ss << toLogString( system.supplyingPowerStates() ) << " "; + ss << toLogString( system.chargePowerPresentStates() ) << " "; + ss << toLogString( system.powerNoGoodStates() ) << " "; + ss << toLogString( system.chargeInhibitedStates() ) << endl; ss << system.batteries().size(); @@ -97,19 +98,19 @@ void updateWithNewData( const OceanServerSystem &from, OceanServerSystem &to ) { - to.rawRecord = from.rawRecord; + to.rawRecord() = from.rawRecord(); typedef map<int,SmartBattery>::const_iterator BatIt; - to.availableBatteries = from.availableBatteries; - to.percentCharge = from.percentCharge; - to.minToEmpty = from.minToEmpty; - to.messageToSystem = from.messageToSystem; - to.chargingStates = from.chargingStates; - to.supplyingPowerStates = from.supplyingPowerStates; - to.chargePowerPresentStates = from.chargePowerPresentStates; - to.powerNoGoodStates = from.powerNoGoodStates; - to.chargeInhibitedStates = from.chargeInhibitedStates; + to.setPercentCharge( from.percentCharge() ); + to.setMinToEmpty( from.minToEmpty() ); + to.setMessageToSystem( from.messageToSystem() ); + to.availableBatteries() = from.availableBatteries(); + to.chargingStates() = from.chargingStates(); + to.supplyingPowerStates() = from.supplyingPowerStates(); + to.chargePowerPresentStates() = from.chargePowerPresentStates(); + to.powerNoGoodStates() = from.powerNoGoodStates(); + to.chargeInhibitedStates() = from.chargeInhibitedStates(); for (BatIt it=from.batteries().begin(); it!=from.batteries().end(); it++) { @@ -177,23 +178,35 @@ } +bool isSystemOnCharge( const gbxsmartbatteryacfr::OceanServerSystem &batterySystem ) +{ + for (unsigned int i=0; i<batterySystem.chargingStates().size(); ++i) + { + if (batterySystem.chargingStates()[i]==true) + return true; + } + return false; +} + + // // Member functions // OceanServerSystem::OceanServerSystem() - : percentCharge(0), - minToEmpty(0), - messageToSystem("") + : isEmpty_(true), + percentCharge_(0), + minToEmpty_(0), + messageToSystem_("") { // fixed number of slots for oceanserver system const int NUM_BATTERY_SLOTS = 8; - availableBatteries.resize(NUM_BATTERY_SLOTS); - chargingStates.resize(NUM_BATTERY_SLOTS); - supplyingPowerStates.resize(NUM_BATTERY_SLOTS); - chargePowerPresentStates.resize(NUM_BATTERY_SLOTS); - powerNoGoodStates.resize(NUM_BATTERY_SLOTS); - chargeInhibitedStates.resize(NUM_BATTERY_SLOTS); + availableBatteries_.resize(NUM_BATTERY_SLOTS); + chargingStates_.resize(NUM_BATTERY_SLOTS); + supplyingPowerStates_.resize(NUM_BATTERY_SLOTS); + chargePowerPresentStates_.resize(NUM_BATTERY_SLOTS); + powerNoGoodStates_.resize(NUM_BATTERY_SLOTS); + chargeInhibitedStates_.resize(NUM_BATTERY_SLOTS); } // read access to all batteries @@ -207,6 +220,8 @@ SmartBattery& OceanServerSystem::battery( unsigned int batteryNumber ) { + isEmpty_=false; + map<int,SmartBattery>::iterator it = batteries_.find(batteryNumber); if ( it==batteries_.end() ) { Modified: gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.h =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.h 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/oceanserversystem.h 2009-11-08 11:51:23 UTC (rev 457) @@ -26,9 +26,12 @@ class OceanServerSystem { public: - + + //! Initialises all data in OceanServerSystem class OceanServerSystem(); - ~OceanServerSystem() {}; + + //! Returns true if no valid data has been set + bool isEmpty() const { return isEmpty_; }; //! Read access to all batteries const std::map<int,SmartBattery>& batteries() const; @@ -42,24 +45,69 @@ //! Erase a battery void eraseBattery( unsigned int batteryNumber ); - //! Average battery values - int percentCharge; - int minToEmpty; - std::string messageToSystem; + //! Set charge in % + void setPercentCharge(int percentCharge) { isEmpty_=false; percentCharge_ = percentCharge; }; + //! Access charget in % + int percentCharge() const { return percentCharge_; }; + //! Set minutes to empty + void setMinToEmpty(int minToEmpty) { isEmpty_=false; minToEmpty_ = minToEmpty; }; + //! Access minutes-to-empty + int minToEmpty() const { return minToEmpty_; }; + //! Set message-to-system string + void setMessageToSystem(const std::string &messageToSystem) { isEmpty_=false; messageToSystem_ = messageToSystem; }; + //! Access message-to-system string + std::string messageToSystem() const { return messageToSystem_; }; - //! Battery module states. Each vector is always of size 8 because OceanServer's Battery - //! Management Modules have a maximum of 8 slots (either 2, 4, or 8 dependent on the model) - std::vector<bool> availableBatteries; - std::vector<bool> chargingStates; - std::vector<bool> supplyingPowerStates; - std::vector<bool> chargePowerPresentStates; - std::vector<bool> powerNoGoodStates; - std::vector<bool> chargeInhibitedStates; + //! Access availableBatteries flags + const std::vector<bool> &availableBatteries() const { return availableBatteries_; }; + //! Set availableBatteries flags + std::vector<bool> &availableBatteries() { isEmpty_=false; return availableBatteries_; }; + //! Access chargingStates flags + const std::vector<bool> &chargingStates() const { return chargingStates_; }; + //! Set chargingStates flags + std::vector<bool> &chargingStates() { isEmpty_=false; return chargingStates_; }; + //! Access supplyingPowerStates flags + const std::vector<bool> &supplyingPowerStates() const { return supplyingPowerStates_; }; + //! Set supplyingPowerStates flags + std::vector<bool> &supplyingPowerStates() { isEmpty_=false; return supplyingPowerStates_; }; + //! Access chargePowerPresentStates flags + const std::vector<bool> &chargePowerPresentStates() const { return chargePowerPresentStates_; }; + //! Set chargePowerPresentStates flags + std::vector<bool> &chargePowerPresentStates() { isEmpty_=false; return chargePowerPresentStates_; }; + //! Access powerNoGoodStates flags + const std::vector<bool> &powerNoGoodStates() const { return powerNoGoodStates_; }; + //! Set powerNoGoodStates flags + std::vector<bool> &powerNoGoodStates() { isEmpty_=false; return powerNoGoodStates_; }; + //! Access chargeInhibitedStates flags + const std::vector<bool> &chargeInhibitedStates() const { return chargeInhibitedStates_; } + //! Set chargeInhibitedStates flags + std::vector<bool> &chargeInhibitedStates() { isEmpty_=false; return chargeInhibitedStates_; } - //! the latest raw record, useful for debugging - std::vector<std::string> rawRecord; + //! Access the latest raw record, useful for debugging + const std::vector<std::string> &rawRecord() const { return rawRecord_; }; + //! Set the latest raw record + std::vector<std::string> &rawRecord() { isEmpty_=false; return rawRecord_; }; private: + + bool isEmpty_; + + // Average battery values + int percentCharge_; + int minToEmpty_; + std::string messageToSystem_; + + // Battery module states. Each vector is always of size 8 because OceanServer's Battery + // Management Modules have a maximum of 8 slots (either 2, 4, or 8 dependent on the model) + std::vector<bool> availableBatteries_; + std::vector<bool> chargingStates_; + std::vector<bool> supplyingPowerStates_; + std::vector<bool> chargePowerPresentStates_; + std::vector<bool> powerNoGoodStates_; + std::vector<bool> chargeInhibitedStates_; + + // the latest raw record, useful for debugging + std::vector<std::string> rawRecord_; // key: slot number, data: a single smart battery module std::map<int,SmartBattery> batteries_; @@ -78,6 +126,9 @@ //! The reaping capability makes sure that battery modules which are no longer connected don't persist. void updateWithNewData( const OceanServerSystem &from, OceanServerSystem &to ); + +//! Returns true if at least one of the battery modules is on charge otherwise false +bool isSystemOnCharge( const OceanServerSystem &batterySystem ); } // namespace Modified: gearbox/trunk/src/gbxsmartbatteryacfr/test/darttest/checksumtest.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/test/darttest/checksumtest.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/test/darttest/checksumtest.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -76,7 +76,7 @@ string checksumStr = ss.str(); for (unsigned int i=0; i<checksumStr.size(); i++) - checksumStr[i] = toupper( checksumStr[i] ); + checksumStr[i] = (char)(toupper( checksumStr[i] )); cout << "Expected checksum result is:\t" << resultHex << endl; cout << "Computed checksum result is:\t" << checksumStr << endl << endl; Modified: gearbox/trunk/src/gbxsmartbatteryacfr/test/longtest.cpp =================================================================== --- gearbox/trunk/src/gbxsmartbatteryacfr/test/longtest.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxsmartbatteryacfr/test/longtest.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -58,10 +58,15 @@ while (true) { - cout << "TRACE(test): Reading record " << numRecords << endl; + cout << "Reading record " << numRecords << endl; numRecords++; gbxsmartbatteryacfr::OceanServerSystem data = oceanserver.getData(); + if ( data.isEmpty() ) + { + cout << "Data was empty. No worries, keep trying to read." << endl; + continue; + } vector<string> shortWarning; vector<string> verboseWarning; const bool printRawRecord = true; Modified: gearbox/trunk/src/gbxutilacfr/exceptions.cpp =================================================================== --- gearbox/trunk/src/gbxutilacfr/exceptions.cpp 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxutilacfr/exceptions.cpp 2009-11-08 11:51:23 UTC (rev 457) @@ -25,7 +25,7 @@ } const char * -Exception::basename( const char *s ) +Exception::basename( const char *s ) const { #ifndef WIN32 return strrchr( s, '/' )+1; @@ -35,7 +35,7 @@ }; std::string -Exception::toMessageString( const char *file, const char *line, const std::string &message ) +Exception::toMessageString( const char *file, const char *line, const std::string &message ) const { std::string msg = "\n *** ERROR("; // not to confuse our local basename() with gbxutilacfr::basename() Modified: gearbox/trunk/src/gbxutilacfr/exceptions.h =================================================================== --- gearbox/trunk/src/gbxutilacfr/exceptions.h 2009-11-07 04:25:00 UTC (rev 456) +++ gearbox/trunk/src/gbxutilacfr/exceptions.h 2009-11-08 11:51:23 UTC (rev 457) @@ -72,12 +72,12 @@ virtual const char* what() const throw() { return message_.c_str(); } protected: - std::string toMessageString( const char *file, const char *line, const std::string &message ); + std::string toMessageString( const char *file, const char *line, const std::string &message ) const; std::string message_; private: - const char *basename( const char *s ); + const char *basename( const char *s ) const; }; //! This exception is raised when something is wrong with the hardware. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |