|
From: <to...@us...> - 2008-06-25 07:27:52
|
Revision: 213
http://gearbox.svn.sourceforge.net/gearbox/?rev=213&view=rev
Author: tobasco
Date: 2008-06-25 00:27:56 -0700 (Wed, 25 Jun 2008)
Log Message:
-----------
first commit of gbxsmartbatteryacfr
Modified Paths:
--------------
gearbox/trunk/submitted/CMakeLists.txt
Added Paths:
-----------
gearbox/trunk/submitted/gbxsmartbatteryacfr/
gearbox/trunk/submitted/gbxsmartbatteryacfr/CMakeLists.txt
gearbox/trunk/submitted/gbxsmartbatteryacfr/exceptions.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/gbxsmartbatteryacfr.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbatteryacfr.dox
gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbatteryparsing.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbatteryparsing.h
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/CMakeLists.txt
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/checksumtest.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/example.cmake.in
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/example.readme
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/fancytest.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/serialtest.cpp
gearbox/trunk/submitted/gbxsmartbatteryacfr/test/simpletest.cpp
Modified: gearbox/trunk/submitted/CMakeLists.txt
===================================================================
--- gearbox/trunk/submitted/CMakeLists.txt 2008-06-24 14:57:10 UTC (rev 212)
+++ gearbox/trunk/submitted/CMakeLists.txt 2008-06-25 07:27:56 UTC (rev 213)
@@ -11,6 +11,7 @@
# Otherwise, maintain alphabetical order.
# E.g. ADD_SUBDIRECTORY( mydir )
ADD_SUBDIRECTORY( flexiport )
+ ADD_SUBDIRECTORY( gbxsmartbatteryacfr )
ADD_SUBDIRECTORY( gbxnovatelacfr )
ADD_SUBDIRECTORY( hokuyo_aist )
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/CMakeLists.txt
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/CMakeLists.txt (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/CMakeLists.txt 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,28 @@
+SET( lib_name GbxSmartBatteryAcfr )
+GBX_ADD_LICENSE( LGPL )
+
+SET( build TRUE )
+GBX_REQUIRE_OPTION( build LIB ${lib_name} ON )
+GBX_REQUIRE_VAR( build LIB ${lib_name} GBX_OS_LINUX "only Linux OS is supported" )
+
+SET( int_libs GbxUtilAcfr GbxSerialAcfr )
+GBX_REQUIRE_TARGETS( build LIB ${lib_name} ${int_libs} )
+
+IF( build )
+
+ INCLUDE( ${GBX_CMAKE_DIR}/UseBasicRules.cmake )
+
+ FILE( GLOB hdrs *.h )
+ FILE( GLOB srcs *.cpp )
+ SET( dep_libs ${int_libs} )
+
+ GBX_ADD_LIBRARY( ${lib_name} SHARED ${srcs} )
+ TARGET_LINK_LIBRARIES( ${lib_name} ${dep_libs} )
+
+ GBX_ADD_HEADERS( gbxsmartbatteryacfr ${hdrs} )
+
+ IF( GBX_BUILD_TESTS )
+ ADD_SUBDIRECTORY( test )
+ ENDIF( GBX_BUILD_TESTS )
+
+ENDIF( build )
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/exceptions.h
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/exceptions.h (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/exceptions.h 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,57 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#ifndef GBX_SMARTBATTERY_ACFR_EXCEPTIONS_H
+#define GBX_SMARTBATTERY_ACFR_EXCEPTIONS_H
+
+#include <exception>
+#include <string>
+
+namespace gbxsmartbatteryacfr {
+
+//!
+//! Exceptions for gbxsmartbatteryacfr
+//!
+class Exception : public std::exception
+{
+public:
+
+ Exception(const char *message)
+ : message_(message) {}
+ Exception(const std::string &message)
+ : message_(message) {}
+
+ virtual ~Exception() throw() {}
+
+ virtual const char* what() const throw() { return message_.c_str(); }
+
+protected:
+
+ std::string message_;
+};
+
+class HardwareReadingException : public Exception
+{
+ public:
+ HardwareReadingException( const char * message )
+ : Exception( message ) {}
+};
+
+class ParsingException : public Exception
+{
+ public:
+ ParsingException( const char * message )
+ : Exception( message ) {}
+};
+
+}
+
+#endif
+
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/gbxsmartbatteryacfr.h
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/gbxsmartbatteryacfr.h (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/gbxsmartbatteryacfr.h 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,21 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#ifndef GBX_SMARTBATTERY_ACFR_H
+#define GBX_SMARTBATTERY_ACFR_H
+
+#include <gbxsmartbatteryacfr/oceanserverparser.h>
+#include <gbxsmartbatteryacfr/oceanserverreader.h>
+#include <gbxsmartbatteryacfr/exceptions.h>
+#include <gbxsmartbatteryacfr/smartbattery.h>
+#include <gbxsmartbatteryacfr/smartbatteryparsing.h>
+
+
+#endif
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.cpp
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.cpp (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.cpp 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,546 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <gbxsmartbatteryacfr/exceptions.h>
+#include <gbxsmartbatteryacfr/smartbatteryparsing.h>
+
+#include "oceanserverparser.h"
+
+using namespace std;
+
+namespace gbxsmartbatteryacfr {
+
+//
+// Helper functions
+//
+string toString( const vector<bool> &flags )
+{
+ stringstream ss;
+ for (unsigned int i=0; i<flags.size(); i++)
+ {
+ ss << flags[i] << " ";
+ }
+ return ss.str();
+}
+
+string toLogString( const vector<bool> &flags )
+{
+ stringstream ss;
+ for (unsigned int i=0; i<flags.size(); i++)
+ {
+ ss << flags[i];
+ }
+ return ss.str();
+}
+
+
+//
+// OceanServerSystem 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;
+
+ map<int,SmartBattery>::const_iterator it;
+ for (it=system.batteries().begin(); it!=system.batteries().end(); it++)
+ {
+ ss << "Data from battery number: " << it->first << endl;
+ ss << toString( it->second ) << endl;
+ }
+
+ return ss.str();
+}
+
+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.batteries().size();
+
+ map<int,SmartBattery>::const_iterator it;
+ for (it=system.batteries().begin(); it!=system.batteries().end(); it++)
+ {
+ ss << it->first << " " << toLogString( it->second ) << endl;
+ }
+
+ return ss.str();
+}
+
+void updateWithNewData( const OceanServerSystem &from,
+ OceanServerSystem &to )
+{
+ 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;
+
+ for (BatIt it=from.batteries().begin(); it!=from.batteries().end(); it++)
+ {
+ const SmartBattery &fromB = from.battery( it->first );
+ SmartBattery &toB = to.battery( it->first );
+
+ if ( fromB.has( ManufacturerAccess ) ) toB.setManufacturerAccess ( fromB.manufacturerAccess () );
+ if ( fromB.has( RemainingCapacityAlarm ) ) toB.setRemainingCapacityAlarm ( fromB.remainingCapacityAlarm () );
+ if ( fromB.has( RemainingTimeAlarm ) ) toB.setRemainingTimeAlarm ( fromB.remainingTimeAlarm () );
+ if ( fromB.has( BatteryMode ) ) toB.setBatteryMode ( fromB.batteryMode () );
+ if ( fromB.has( AtRate ) ) toB.setAtRate ( fromB.atRate () );
+ if ( fromB.has( AtRateTimeToFull ) ) toB.setAtRateTimeToFull ( fromB.atRateTimeToFull () );
+ if ( fromB.has( AtRateTimeToEmpty ) ) toB.setAtRateTimeToEmpty ( fromB.atRateTimeToEmpty () );
+ if ( fromB.has( AtRateOk ) ) toB.setAtRateOk ( fromB.atRateOk () );
+ if ( fromB.has( Temperature ) ) toB.setTemperature ( fromB.temperature () );
+ if ( fromB.has( Voltage ) ) toB.setVoltage ( fromB.voltage () );
+ if ( fromB.has( Current ) ) toB.setCurrent ( fromB.current () );
+ if ( fromB.has( AverageCurrent ) ) toB.setAverageCurrent ( fromB.averageCurrent () );
+ if ( fromB.has( MaxError ) ) toB.setMaxError ( fromB.maxError () );
+ if ( fromB.has( RelativeStateOfCharge ) ) toB.setRelativeStateOfCharge ( fromB.relativeStateOfCharge () );
+ if ( fromB.has( AbsoluteStateOfCharge ) ) toB.setAbsoluteStateOfCharge ( fromB.absoluteStateOfCharge () );
+ if ( fromB.has( RemainingCapacity ) ) toB.setRemainingCapacity ( fromB.remainingCapacity () );
+ if ( fromB.has( FullChargeCapacity ) ) toB.setFullChargeCapacity ( fromB.fullChargeCapacity () );
+ if ( fromB.has( RunTimeToEmpty ) ) toB.setRunTimeToEmpty ( fromB.runTimeToEmpty () );
+ if ( fromB.has( AverageTimeToEmpty ) ) toB.setAverageTimeToEmpty ( fromB.averageTimeToEmpty () );
+ if ( fromB.has( AverageTimeToFull ) ) toB.setAverageTimeToFull ( fromB.averageTimeToFull () );
+ if ( fromB.has( ChargingCurrent ) ) toB.setChargingCurrent ( fromB.chargingCurrent () );
+ if ( fromB.has( ChargingVoltage ) ) toB.setChargingVoltage ( fromB.chargingVoltage () );
+ if ( fromB.has( BatteryStatus ) ) toB.setBatteryStatus ( fromB.batteryStatus () );
+ if ( fromB.has( CycleCount ) ) toB.setCycleCount ( fromB.cycleCount () );
+ if ( fromB.has( DesignCapacity ) ) toB.setDesignCapacity ( fromB.designCapacity () );
+ if ( fromB.has( DesignVoltage ) ) toB.setDesignVoltage ( fromB.designVoltage () );
+ if ( fromB.has( SpecificationInfo ) ) toB.setSpecificationInfo ( fromB.specificationInfo () );
+ if ( fromB.has( ManufactureDate ) ) toB.setManufactureDate ( fromB.manufactureDate () );
+ if ( fromB.has( SerialNumber ) ) toB.setSerialNumber ( fromB.serialNumber () );
+ if ( fromB.has( ManufacturerName ) ) toB.setManufacturerName ( fromB.manufacturerName () );
+ if ( fromB.has( DeviceName ) ) toB.setDeviceName ( fromB.deviceName () );
+ if ( fromB.has( DeviceChemistry ) ) toB.setDeviceChemistry ( fromB.deviceChemistry () );
+ if ( fromB.has( ManufacturerData ) ) toB.setManufacturerData ( fromB.manufacturerData () );
+ }
+
+ // check if reaping needs to be done
+ if ( from.batteries().size() == to.batteries().size() )
+ return;
+
+ // store batteries to be reaped in a vector
+ vector<int> reapingIds;
+
+ // go through all 'to' batteries and check if they are also in 'from'
+ for (BatIt it=to.batteries().begin(); it!=to.batteries().end(); it++)
+ {
+ const int batId = it->first;
+
+ BatIt itFrom = from.batteries().find( batId );
+ if ( itFrom == from.batteries().end() ) {
+ // battery is in 'to' but not in 'from' -> needs to be deleted
+ reapingIds.push_back( batId );
+ }
+ }
+
+ // erase batteries
+ for (unsigned int i=0; i<reapingIds.size(); i++) {
+ to.eraseBattery( reapingIds[i] );
+ }
+
+}
+
+
+//
+// OceanServerSystem member functions
+//
+
+OceanServerSystem::OceanServerSystem()
+ : 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);
+}
+
+// read access to all batteries
+const map<int,SmartBattery>&
+OceanServerSystem::batteries() const
+{
+ return batteries_;
+}
+
+// write access to single battery
+SmartBattery&
+OceanServerSystem::battery( unsigned int batteryNumber )
+{
+ map<int,SmartBattery>::iterator it = batteries_.find(batteryNumber);
+ if ( it==batteries_.end() )
+ {
+ // we don't have it, so instantiate a new one
+ SmartBattery b;
+ batteries_[batteryNumber] = b;
+ return batteries_[batteryNumber];
+ }
+
+ return it->second;
+}
+
+// read access to single battery
+const SmartBattery&
+OceanServerSystem::battery( unsigned int batteryNumber ) const
+{
+ map<int,SmartBattery>::const_iterator it = batteries_.find(batteryNumber);
+ if ( it==batteries_.end() )
+ {
+ stringstream ss;
+ ss << "ERROR(OceanServerParser.cpp): trying to read from non-existent battery " << batteryNumber;
+ throw ParsingException( ss.str().c_str() );
+ }
+ return it->second;
+}
+
+void
+OceanServerSystem::eraseBattery( unsigned int batteryNumber )
+{
+ batteries_.erase( batteries_.find( batteryNumber ) );
+}
+
+//
+// OceanServerParser member functions
+//
+
+OceanServerParser::OceanServerParser( gbxutilacfr::Tracer &tracer )
+ : tracer_(tracer)
+{
+}
+
+void
+OceanServerParser::parseSystemData( const map<string,string> &keyValuePairs,
+ OceanServerSystem &batterySystem )
+{
+ map<string,string>::const_iterator it;
+
+ for (it=keyValuePairs.begin(); it!=keyValuePairs.end(); it++)
+ {
+ if (it->first=="01") {
+ batterySystem.minToEmpty = readMinutes(it->second);
+ }
+ else if (it->first=="02") {
+ // reserved, do nothing
+ }
+ else if (it->first=="03") {
+ batterySystem.messageToSystem = it->second;
+ }
+ else if (it->first=="04") {
+ batterySystem.percentCharge = readPercentByte(it->second);
+ }
+ else
+ {
+ stringstream ss;
+ ss << "OceanServerParser: Unknown System key: " << it->first;
+ throw ParsingException(ss.str().c_str());
+ }
+ }
+}
+
+void
+OceanServerParser::parseControllerData( const map<string,string> &keyValuePairs,
+ OceanServerSystem &batterySystem )
+{
+ map<string,string>::const_iterator it;
+
+ for (it=keyValuePairs.begin(); it!=keyValuePairs.end(); it++)
+ {
+ vector<bool> states;
+
+ if (it->first=="01") {
+ readSingleByte(it->second, states);
+ batterySystem.availableBatteries = states;
+ }
+ else if (it->first=="02") {
+ readSingleByte(it->second, states);
+ batterySystem.chargingStates = states;
+ }
+ else if (it->first=="03") {
+ readSingleByte(it->second, states);
+ batterySystem.supplyingPowerStates = states;
+ }
+ else if (it->first=="04") {
+ // reserved, do nothing
+ }
+ else if (it->first=="05") {
+ readSingleByte(it->second, states);
+ batterySystem.chargePowerPresentStates = states;
+ }
+ else if (it->first=="06") {
+ readSingleByte(it->second, states);
+ batterySystem.powerNoGoodStates = states;
+ }
+ else if (it->first=="07") {
+ readSingleByte(it->second, states);
+ batterySystem.chargeInhibitedStates = states;
+ }
+ else
+ {
+ stringstream ss;
+ ss << "OceanServerParser: Unknown controller key: " << it->first;
+ throw ParsingException(ss.str().c_str());
+ }
+
+ }
+
+}
+
+void
+OceanServerParser::parseSingleBatteryData( const map<string,string> &keyValuePairs,
+ unsigned int batteryNum,
+ OceanServerSystem &batterySystem )
+{
+ map<string,string>::const_iterator it;
+
+ // get a reference to the battery whose fields we're updating
+ SmartBattery &bat = batterySystem.battery( batteryNum );
+
+ for (it=keyValuePairs.begin(); it!=keyValuePairs.end(); it++)
+ {
+ SmartBatteryDataField smartField = stringToSmartField( it->first );
+
+ switch( smartField )
+ {
+ case ManufacturerAccess:
+ bat.setManufacturerAccess( read16Flags( it->second ) ); break;
+ case RemainingCapacityAlarm:
+ bat.setRemainingCapacityAlarm( readCapacity( it->second ) ); break;
+ case RemainingTimeAlarm:
+ bat.setRemainingTimeAlarm( readMinutes( it->second ) ); break;
+ case BatteryMode:
+ bat.setBatteryMode( read16Flags( it->second ) ); break;
+ case AtRate:
+ bat.setAtRate( readRate( it->second ) ); break;
+ case AtRateTimeToFull:
+ bat.setAtRateTimeToFull( readMinutes( it->second ) ); break;
+ case AtRateTimeToEmpty:
+ bat.setAtRateTimeToEmpty( readMinutes( it->second ) ); break;
+ case AtRateOk:
+ bat.setAtRateOk( readBool( it->second ) ); break;
+ case Temperature:
+ bat.setTemperature( readTemperature( it->second ) ); break;
+ case Voltage:
+ bat.setVoltage( readVoltage( it->second ) ); break;
+ case Current:
+ bat.setCurrent( readCurrent( it->second ) ); break;
+ case AverageCurrent:
+ bat.setAverageCurrent( readCurrent( it->second ) ); break;
+ case MaxError:
+ bat.setMaxError( readPercentWord( it->second ) ); break;
+ case RelativeStateOfCharge:
+ bat.setRelativeStateOfCharge( readPercentWord( it->second ) ); break;
+ case AbsoluteStateOfCharge:
+ bat.setAbsoluteStateOfCharge( readPercentWord( it->second ) ); break;
+ case RemainingCapacity:
+ bat.setRemainingCapacity( readCapacity( it->second ) ); break;
+ case FullChargeCapacity:
+ bat.setFullChargeCapacity( readCapacity( it->second ) ); break;
+ case RunTimeToEmpty:
+ bat.setRunTimeToEmpty( readMinutes( it->second ) ); break;
+ case AverageTimeToEmpty:
+ bat.setAverageTimeToEmpty( readMinutes( it->second ) ); break;
+ case AverageTimeToFull:
+ bat.setAverageTimeToFull( readMinutes( it->second ) ); break;
+ case ChargingCurrent:
+ bat.setChargingCurrent( readCurrent( it->second ) ); break;
+ case ChargingVoltage:
+ bat.setChargingVoltage( readVoltage( it->second ) ); break;
+ case BatteryStatus:
+ bat.setBatteryStatus( read16Flags( it->second ) ); break;
+ case CycleCount:
+ bat.setCycleCount( readCount (it->second) ); break;
+ case DesignCapacity:
+ bat.setDesignCapacity( readCapacity( it->second ) ); break;
+ case DesignVoltage:
+ bat.setDesignVoltage( readVoltage( it->second ) ); break;
+ case SpecificationInfo:
+ bat.setSpecificationInfo( read16Flags( it->second ) ); break;
+ case ManufactureDate:
+ bat.setManufactureDate( read16Flags( it->second ) ); break;
+ case SerialNumber:
+ bat.setSerialNumber( readNumber( it->second ) ); break;
+ case ManufacturerName:
+ bat.setManufacturerName( it->second ); break;
+ case DeviceName:
+ bat.setDeviceName( it->second ); break;
+ case DeviceChemistry:
+ bat.setDeviceChemistry( it->second ); break;
+ case ManufacturerData:
+ bat.setManufacturerData( read16Flags( it->second ) ); break;
+ case NUM_SMARTBATTERY_FIELDS:
+ default:
+ stringstream ss; ss << "OceanServerParser: Unknown Battery key: " << it->first;
+ throw ParsingException( ss.str().c_str() );
+ }
+ }
+
+}
+
+void
+OceanServerParser::parseFields( vector<string> &fields,
+ OceanServerSystem &batterySystem )
+{
+ if (fields.size()==0) return;
+
+ // save the msgType string and remove from vector
+ string msgType = fields[0];
+ vector<string>::iterator it = fields.begin();
+ fields.erase( it );
+
+ // get the msg type key (S,C,B)
+ const string &msgTypeKey = msgType.substr(0,2);
+
+ // make key-value pairs
+ map<string,string> keyValuePairs;
+ toKeyValuePairs( fields, keyValuePairs, tracer_ );
+
+ if (msgTypeKey=="$S")
+ {
+ parseSystemData( keyValuePairs, batterySystem );
+ }
+ else if (msgTypeKey=="$C")
+ {
+ parseControllerData( keyValuePairs, batterySystem );
+ }
+ else if (msgTypeKey=="$B")
+ {
+ stringstream ss(msgType.substr(3));
+ int batteryNum;
+ ss >> batteryNum;
+ parseSingleBatteryData( keyValuePairs, batteryNum, batterySystem );
+ }
+ else
+ {
+ stringstream ss;
+ ss << "OceanServerParser: Unknown message type: " << msgTypeKey;
+ throw ParsingException(ss.str().c_str());
+ }
+}
+
+bool
+OceanServerParser::atBeginningOfRecord( const char* line )
+{
+ vector<string> tokens;
+ splitIntoFields( line, tokens, ",");
+
+ if (tokens.size()>0) {
+ if (tokens[0]!="$S") {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+OceanServerParser::atEndOfRecord( const char* line )
+{
+ vector<string> tokens;
+ splitIntoFields( line, tokens, ",");
+
+ if (tokens.size()>0) {
+ if (tokens[0]=="$S") return true;
+ }
+ return false;
+}
+
+
+void
+OceanServerParser::parse( vector<string> &stringList,
+ OceanServerSystem &batterySystem )
+{
+
+ //
+ // Uncomment for DEBUG information
+ //
+
+ stringstream ss;
+ ss << "OceanServerParser: Received the following input: " << endl;
+ for (unsigned int i=0; i<stringList.size(); i++)
+ {
+ const string &str = stringList[i];
+ ss << i << ": " << str;
+
+ // output in hex
+ ss << i << " hex: ";
+ for (unsigned k=0; k<str.size(); k++)
+ {
+ unsigned int charValue = (unsigned int)str[k];
+ ss << str[k] << ": " << std::hex << charValue << " ";
+ }
+ ss << std::dec;
+
+ }
+ ss << endl;
+ tracer_.debug( ss.str(), 10 );
+
+ for (unsigned int i=0; i<stringList.size(); i++)
+ {
+ const string &line = stringList[i];
+
+ // check for control characters in the line (sometimes they are accidently inserted)
+ // don't check the last 2 characters: they're \0 and \n
+ for (unsigned int k=0; k<line.size()-2; k++)
+ {
+ if ( iscntrl( line[k] ) )
+ throw ParsingException("ERROR(oceanserverparser.cpp): Found a control character (binary) in the string!");
+ }
+
+ // divide the line into 2 parts: data and checksum (if present)
+ vector<string> checksumList;
+ splitIntoFields(line, checksumList, "%" );
+ if (checksumList.size()==2)
+ {
+ // we have a checksum, is it correct?
+ if (!isChecksumValid( checksumList[0], checksumList[1] ) )
+ throw ParsingException("ERROR(oceanserverparser.cpp): Checksum failed!");
+ }
+
+ // divide the data into individual fields and parse
+ if (checksumList.size()==0)
+ throw ParsingException("ERROR(oceanserverparser.cpp): String length is 0");
+ vector<string> fields;
+ splitIntoFields( checksumList[0], fields, ",");
+ parseFields( fields, batterySystem );
+ }
+}
+
+}
+
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.h
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.h (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverparser.h 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,123 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#ifndef OCEANSERVER_PARSER_H
+#define OCEANSERVER_PARSER_H
+
+#include <map>
+#include <gbxutilacfr/tracer.h>
+#include <gbxsmartbatteryacfr/smartbattery.h>
+
+namespace gbxsmartbatteryacfr
+{
+
+//!
+//! Class representing the OceanServer battery system data
+//! Contains average values of the whole system and values from individual batteries
+//!
+//! @author Tobias Kaupp
+//!
+class OceanServerSystem
+{
+ public:
+
+ OceanServerSystem();
+ ~OceanServerSystem() {};
+
+ // read access to all batteries
+ const std::map<int,SmartBattery>& batteries() const;
+
+ // easy write access to single battery, instantiates a new one if it doesn't exist
+ SmartBattery& battery( unsigned int batteryNumber );
+
+ // easy read access to single battery, battery must exist
+ const SmartBattery& battery( unsigned int batteryNumber ) const;
+
+ // erase a battery
+ void eraseBattery( unsigned int batteryNumber );
+
+ // average battery values
+ int percentCharge;
+ int minToEmpty;
+ std::string messageToSystem;
+
+ // values from the controller
+ // each vector is always of size 8 because oceanserver system has 8 slots
+ std::vector<bool> availableBatteries;
+ std::vector<bool> chargingStates;
+ std::vector<bool> supplyingPowerStates;
+ std::vector<bool> chargePowerPresentStates;
+ std::vector<bool> powerNoGoodStates;
+ std::vector<bool> chargeInhibitedStates;
+
+ private:
+ std::map<int,SmartBattery> batteries_;
+};
+
+//! Puts all available data into a human-readable string
+std::string toString( const OceanServerSystem &system );
+
+//! Puts all available data into a machine-readable ASCII string
+std::string toLogString( const OceanServerSystem &system );
+
+//! Updates all fields in 'to' with data from 'from'. Also reapes batteries in 'to' if they are not in 'from'.
+//! Has persistence capabilities: if fields in 'from' are not set and corresponding fields in 'to' are set, the ones in 'to' are kept.
+//! Use case: a class stores 'to' as a member variable, receives the latest records into 'from', calls this function to update 'to'.
+//! The reaping capability makes sure that battery modules which are no longer connected don't persist.
+void updateWithNewData( const OceanServerSystem &from,
+ OceanServerSystem &to );
+
+//!
+//! Class to parse the hex data the oceanserver battery controller spits out
+//!
+//! @author Tobias Kaupp
+//!
+class OceanServerParser
+{
+public:
+
+ OceanServerParser( gbxutilacfr::Tracer &tracer );
+ ~OceanServerParser() {};
+
+ //! Expects a full record of batterydata as a stringList (one line per string) produced by the oceanserver controller.
+ //! Parses each line and sets corresponding fields in batterySystem
+ void parse( std::vector<std::string> &stringList,
+ OceanServerSystem &batterySystem );
+
+ //! Checks whether the passed string (one line) is the first line of the record
+ bool atBeginningOfRecord( const char *string );
+
+ //! Checks whether the passed string (one line) is the end of the record
+ bool atEndOfRecord( const char *string );
+
+private:
+
+ gbxutilacfr::Tracer &tracer_;
+
+ // parsing functions
+ void parseFields( std::vector<std::string> &fields,
+ OceanServerSystem &batterySystem );
+
+ void parseSystemData( const std::map<std::string,std::string> &keyValuePairs,
+ OceanServerSystem &batterySystem);
+
+ void parseControllerData( const std::map<std::string,std::string> &keyValuePairs,
+ OceanServerSystem &batterySystem);
+
+ void parseSingleBatteryData( const std::map<std::string,std::string> &keyValuePairs,
+ unsigned int batteryNum,
+ OceanServerSystem &batterySystem);
+
+};
+
+
+} // namespace
+
+#endif
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.cpp
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.cpp (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.cpp 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,190 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <gbxsmartbatteryacfr/exceptions.h>
+#include <gbxsmartbatteryacfr/oceanserverparser.h>
+
+#include "oceanserverreader.h"
+
+using namespace std;
+
+namespace gbxsmartbatteryacfr {
+
+static const int BAUDRATE = 19200;
+static const int TIMEOUT_SEC = 2;
+
+OceanServerReader::OceanServerReader( const string &device,
+ gbxutilacfr::Tracer &tracer )
+ : serial_( device, BAUDRATE, gbxserialacfr::Serial::Timeout(TIMEOUT_SEC,0) ),
+ tracer_(tracer),
+ parser_(tracer),
+ firstTime_(true)
+{
+ // some menu entries from the OceanServer system - used to recognize whether
+ // we are connected to the right device
+ oceanServerStrings_.push_back(" S - Setup Controller");
+ oceanServerStrings_.push_back(" B - Battery Status");
+ oceanServerStrings_.push_back(" X - Host HEX");
+ oceanServerStrings_.push_back(" H - Help");
+ oceanServerStrings_.push_back(" www.ocean-server.com");
+
+ checkConnection();
+
+ // send the command to start reading data
+ serial_.flush();
+
+ const char startReading = 'X';
+
+ serial_.write(&startReading, 1);
+}
+
+bool
+OceanServerReader::isOceanServerSystem( const char* oceanServerString )
+{
+ for (unsigned int i=0; i<oceanServerStrings_.size(); i++)
+ {
+ // if the first 8 characters agree we are pretty sure we have an OceanServerSystem
+ if (strncmp(oceanServerStrings_[i].c_str(),oceanServerString,8)==0) return true;
+ }
+ return false;
+}
+
+void
+OceanServerReader::checkConnection()
+{
+ tracer_.info( "OceanServerReader: Checking connection to serial port" );
+
+ // a blank will get us into menu mode
+ const char menuMode = ' ';
+ serial_.write(&menuMode, 1);
+
+ // if we were in battery reading mode before, we might have to skip quite
+ // a few lines until we get something from the menu
+ const int maxTries = 40;
+ int numTries=0;
+
+ // for tracer output
+ stringstream ss;
+
+ while(true)
+ {
+ ss.str(""); ss << "OceanServerReader: Trying to read from serial port with timeout of " << TIMEOUT_SEC << "s" << endl;
+ tracer_.info( ss.str() );
+
+ string serialData;
+ int ret = serial_.readLine( serialData );
+ if (ret<0) {
+ throw HardwareReadingException("Connected to the wrong serial port. Timed out while trying to read a line.");
+ }
+ if ( isOceanServerSystem(serialData.c_str()) ) {
+ tracer_.info( "Oceanserverreader.cpp: We are connected to an Oceanserver system. Good." );
+ break;
+ }
+ numTries++;
+ ss.str(""); ss << "OceanServerReader: Trying to find out whether this is an oceanserver system. Attempt number " << numTries << "/" << maxTries << ".";
+ tracer_.info( ss.str() );
+ if (numTries>=maxTries) {
+ throw HardwareReadingException("Connected to the wrong serial port. Didn't recognize any of the strings.");
+ }
+ }
+}
+
+OceanServerReader::~OceanServerReader()
+{
+}
+
+void
+OceanServerReader::tryToReadLineFromSerialPort( std::string &serialData )
+{
+ const int maxTries=5;
+ int numTries=0;
+
+ while(true)
+ {
+ int ret = serial_.readLine( serialData );
+
+ if (ret>0) break;
+
+ numTries++;
+ if (numTries>=maxTries) {
+ stringstream ss;
+ ss << "Can't read data from serial port. Timed out and/or empty strings " << maxTries << " times in a row.";
+ throw HardwareReadingException( ss.str().c_str() );
+ }
+ }
+}
+
+void
+OceanServerReader::read( OceanServerSystem &system )
+{
+ string serialData;
+ vector<string> stringList;
+
+ if (firstTime_)
+ {
+ // (1) Wait until we got the beginning of the record
+ while(true)
+ {
+ tryToReadLineFromSerialPort( serialData );
+ if (parser_.atBeginningOfRecord( serialData.c_str() )) break;
+ }
+
+ tracer_.debug( "OceanServerReader: Beginning of a new record", 5 );
+
+ // (2) Add the first line to the stringlist
+ stringList.push_back( serialData );
+ }
+ else
+ {
+
+ tracer_.debug( "OceanServerReader: We already have the first line from the previous record", 5 );
+ stringList.push_back( beginningRecordLine_ );
+ }
+
+ try {
+
+ // (3) Read the rest of the record line-by-line
+ while(true)
+ {
+ tryToReadLineFromSerialPort( serialData );
+ if ( parser_.atEndOfRecord( serialData.c_str() ) )
+ {
+ tracer_.debug( "OceanServerReader: End of record", 5 );
+ parser_.parse( stringList, system );
+ break;
+ }
+ stringList.push_back(serialData);
+ }
+
+ // (4) Save the last line for next time, it's the S-record
+ // Otherwise we'd miss a record
+ beginningRecordLine_ = serialData;
+ if (firstTime_) {
+ firstTime_ = false;
+ }
+ }
+ catch (ParsingException &e)
+ {
+ stringstream ss;
+ ss << "OceanServerReader: Caught ParsingException: " << e.what() << ". ";
+ ss << "It's not critical, we are trying to find the beginning of a new record.";
+ tracer_.warning( ss.str() );
+ firstTime_ = true;
+
+ // we have to rethrow, so that the caller knows that it may receive a corrupt record
+ throw;
+ }
+}
+
+}
+
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.h
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.h (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/oceanserverreader.h 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,62 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#ifndef OCEANSERVER_READER_H
+#define OCEANSERVER_READER_H
+
+#include <string>
+#include <gbxserialacfr/serial.h>
+#include <gbxutilacfr/tracer.h>
+
+#include <gbxsmartbatteryacfr/oceanserverparser.h>
+
+
+namespace gbxsmartbatteryacfr
+{
+
+//!
+//! Class to read data from the oceanserver battery system:
+//! (1) connects to the serial port
+//! (2) reads from the serial port and parses data
+//!
+//! @author Tobias Kaupp
+//!
+class OceanServerReader
+{
+public:
+
+ //! May throw SerialPortException
+ OceanServerReader( const std::string &device,
+ gbxutilacfr::Tracer &tracer );
+
+ ~OceanServerReader();
+
+ //! May throw HardwareReadingException
+ void read( OceanServerSystem &system );
+
+private:
+
+ bool isOceanServerSystem( const char* oceanServerString );
+ std::vector<std::string> oceanServerStrings_;
+
+ gbxserialacfr::Serial serial_;
+ gbxutilacfr::Tracer& tracer_;
+ gbxsmartbatteryacfr::OceanServerParser parser_;
+
+ void checkConnection();
+ void tryToReadLineFromSerialPort( std::string &serialData );
+
+ std::string beginningRecordLine_;
+ bool firstTime_;
+};
+
+} // namespace
+
+#endif
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.cpp
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.cpp (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.cpp 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,257 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include "smartbattery.h"
+
+using namespace std;
+
+namespace gbxsmartbatteryacfr {
+
+SmartBatteryDataField stringToSmartField( const string &fieldStr )
+{
+ if (fieldStr=="00") return ManufacturerAccess;
+ else if (fieldStr=="01") return RemainingCapacityAlarm;
+ else if (fieldStr=="02") return RemainingTimeAlarm;
+ else if (fieldStr=="03") return BatteryMode;
+ else if (fieldStr=="04") return AtRate;
+ else if (fieldStr=="05") return AtRateTimeToFull;
+ else if (fieldStr=="06") return AtRateTimeToEmpty;
+ else if (fieldStr=="07") return AtRateOk;
+ else if (fieldStr=="08") return Temperature;
+ else if (fieldStr=="09") return Voltage;
+ else if (fieldStr=="0A") return Current;
+ else if (fieldStr=="0B") return AverageCurrent;
+ else if (fieldStr=="0C") return MaxError;
+ else if (fieldStr=="0D") return RelativeStateOfCharge;
+ else if (fieldStr=="0E") return AbsoluteStateOfCharge;
+ else if (fieldStr=="0F") return RemainingCapacity;
+ else if (fieldStr=="10") return FullChargeCapacity;
+ else if (fieldStr=="11") return RunTimeToEmpty;
+ else if (fieldStr=="12") return AverageTimeToEmpty;
+ else if (fieldStr=="13") return AverageTimeToFull;
+ else if (fieldStr=="14") return ChargingCurrent;
+ else if (fieldStr=="15") return ChargingVoltage;
+ else if (fieldStr=="16") return BatteryStatus;
+ else if (fieldStr=="17") return CycleCount;
+ else if (fieldStr=="18") return DesignCapacity;
+ else if (fieldStr=="19") return DesignVoltage;
+ else if (fieldStr=="1A") return SpecificationInfo;
+ else if (fieldStr=="1B") return ManufactureDate;
+ else if (fieldStr=="1C") return SerialNumber;
+ else if (fieldStr=="20") return ManufacturerName;
+ else if (fieldStr=="21") return DeviceName;
+ else if (fieldStr=="22") return DeviceChemistry;
+ else if (fieldStr=="23") return ManufacturerData;
+ else cout << "ERROR: Unknown field: " << fieldStr << endl;
+
+ return NUM_SMARTBATTERY_FIELDS;
+}
+
+string toString( const SmartBattery &b )
+{
+ stringstream ss;
+
+ if ( b.has( ManufacturerAccess ) )
+ ss << "ManufacturerAccess (16 bits): " << std::hex << b.manufacturerAccess() << endl;
+ if ( b.has( RemainingCapacityAlarm ) )
+ ss << "RemainingCapacityAlarm (mAh or 10mWh): " << std::dec << b.remainingCapacityAlarm() << endl;
+ if ( b.has( RemainingTimeAlarm ) )
+ ss << "RemainingTimeAlarm (min): " << std::dec << b.remainingTimeAlarm() << endl;
+ if ( b.has( BatteryMode ) )
+ ss << "BatteryMode (16 bits): " << std::hex << b.batteryMode() << endl;
+ if ( b.has( AtRate ) )
+ ss << "AtRate (mA or 10mW): " << std::dec << b.atRate() << endl;
+ if ( b.has( AtRateTimeToFull ) )
+ ss << "AtRateTimeToFull (min): " << std::dec << b.atRateTimeToFull() << endl;
+ if ( b.has( AtRateTimeToEmpty ) )
+ ss << "AtRateTimeToEmpty (min): " << std::dec << b.atRateTimeToEmpty() << endl;
+ if ( b.has( AtRateOk ) )
+ ss << "AtRateOk (bool): " << std::dec << b.atRateOk() << endl;
+ if ( b.has( Temperature ) )
+ ss << "Temperature (degC): " << std::dec << b.temperature() << endl;
+ if ( b.has( Voltage ) )
+ ss << "Voltage (V): " << std::dec << b.voltage() << endl;
+ if ( b.has( Current ) )
+ ss << "Current (A): " << std::dec << b.current() << endl;
+ if ( b.has( AverageCurrent ) )
+ ss << "AverageCurrent (A): " << std::dec << b.averageCurrent() << endl;
+ if ( b.has( MaxError ) )
+ ss << "MaxError (%): " << std::dec << b.maxError() << endl;
+ if ( b.has( RelativeStateOfCharge ) )
+ ss << "RelativeStateOfCharge (%): " << std::dec << b.relativeStateOfCharge() << endl;
+ if ( b.has( AbsoluteStateOfCharge ) )
+ ss << "AbsoluteStateOfCharge (%): " << std::dec << b.absoluteStateOfCharge() << endl;
+ if ( b.has( RemainingCapacity ) )
+ ss << "RemainingCapacity (mAh or 10 mWh): " << std::dec << b.remainingCapacity() << endl;
+ if ( b.has( FullChargeCapacity ) )
+ ss << "FullChargeCapacity (mAh or 10 mWh): " << std::dec << b.fullChargeCapacity() << endl;
+ if ( b.has( RunTimeToEmpty ) )
+ ss << "RunTimeToEmpty (min): " << std::dec << b.runTimeToEmpty() << endl;
+ if ( b.has( AverageTimeToEmpty ) )
+ ss << "AverageTimeToEmpty (min): " << std::dec << b.averageTimeToEmpty() << endl;
+ if ( b.has( AverageTimeToFull ) )
+ ss << "AverageTimeToFull (min): " << std::dec << b.averageTimeToFull() << endl;
+ if ( b.has( ChargingCurrent ) )
+ ss << "ChargingCurrent (A): " << std::dec << b.chargingCurrent() << endl;
+ if ( b.has( ChargingVoltage ) )
+ ss << "ChargingVoltage (V): " << std::dec << b.chargingVoltage() << endl;
+ if ( b.has( BatteryStatus ) )
+ ss << "BatteryStatus (16 bits): " << std::hex << b.batteryStatus() << endl;
+ if ( b.has( CycleCount ) )
+ ss << "CycleCount (number): " << std::dec << b.cycleCount() << endl;
+ if ( b.has( DesignCapacity ) )
+ ss << "DesignCapacity (mAh or 10 mWh): " << std::dec << b.designCapacity() << endl;
+ if ( b.has( DesignVoltage ) )
+ ss << "DesignVoltage (V): " << std::dec << b.designVoltage() << endl;
+ if ( b.has( SpecificationInfo ) )
+ ss << "SpecificationInfo (16 bits): " << std::hex << b.specificationInfo() << endl;
+ if ( b.has( ManufactureDate ) )
+ ss << "ManufactureDate (16 bits): " << std::hex << b.manufactureDate() << endl;
+ if ( b.has( SerialNumber ) )
+ ss << "SerialNumber (number): " << std::dec << b.serialNumber() << endl;
+ if ( b.has( ManufacturerName ) )
+ ss << "ManufacturerName: " << b.manufacturerName() << endl;
+ if ( b.has( DeviceName ) )
+ ss << "DeviceName: " << b.deviceName() << endl;
+ if ( b.has( DeviceChemistry ) )
+ ss << "DeviceChemistry: " << b.deviceChemistry() << endl;
+ if ( b.has( ManufacturerData ) )
+ ss << "ManufacturerData (16 bits): " << std::hex << b.manufacturerData() << endl;
+
+ return ss.str();
+}
+
+// For logging, we want a data entry per field, so it's easier to parse.
+// For cases where data is not available (NA), we define "special" data entries for each type.
+// This is a bit sketchy but ok for the purpose of simpler logging.
+const int NA_DEC = -999;
+const uint16_t NA_HEX = 11111;
+const std::string NA_STR = "XXXX";
+
+string toLogString( const SmartBattery &b )
+{
+ stringstream ss;
+
+ if ( b.has( ManufacturerAccess ) ) ss << std::hex << b.manufacturerAccess();
+ else ss << std::hex << NA_HEX; ss << " ";
+
+ if ( b.has( RemainingCapacityAlarm ) ) ss << std::dec << b.remainingCapacityAlarm();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( RemainingTimeAlarm ) ) ss << std::dec << b.remainingTimeAlarm();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( BatteryMode ) ) ss << std::hex << b.batteryMode();
+ else ss << std::hex << NA_HEX; ss << " ";
+
+ if ( b.has( AtRate ) ) ss << std::dec << b.atRate();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AtRateTimeToFull ) ) ss << std::dec << b.atRateTimeToFull();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AtRateTimeToEmpty ) ) ss << std::dec << b.atRateTimeToEmpty();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AtRateOk ) ) ss << std::dec << b.atRateOk();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( Temperature ) ) ss << std::dec << b.temperature();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( Voltage ) ) ss << std::dec << b.voltage();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( Current ) ) ss << std::dec << b.current();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AverageCurrent ) ) ss << std::dec << b.averageCurrent();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( MaxError ) ) ss << std::dec << b.maxError();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( RelativeStateOfCharge ) ) ss << std::dec << b.relativeStateOfCharge();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AbsoluteStateOfCharge ) ) ss << std::dec << b.absoluteStateOfCharge();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( RemainingCapacity ) ) ss << std::dec << b.remainingCapacity();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( FullChargeCapacity ) ) ss << std::dec << b.fullChargeCapacity();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( RunTimeToEmpty ) ) ss << std::dec << b.runTimeToEmpty();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AverageTimeToEmpty ) ) ss << std::dec << b.averageTimeToEmpty();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( AverageTimeToFull ) ) ss << std::dec << b.averageTimeToFull();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( ChargingCurrent ) ) ss << std::dec << b.chargingCurrent();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( ChargingVoltage ) ) ss << std::dec << b.chargingVoltage();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( BatteryStatus ) ) ss << std::hex << b.batteryStatus();
+ else ss << std::hex << NA_HEX; ss << " ";
+
+ if ( b.has( CycleCount ) ) ss << std::dec << b.cycleCount();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( DesignCapacity ) ) ss << std::dec << b.designCapacity();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( DesignVoltage ) ) ss << std::dec << b.designVoltage();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( SpecificationInfo ) ) ss << std::hex << b.specificationInfo();
+ else ss << std::hex << NA_HEX; ss << " ";
+
+ if ( b.has( ManufactureDate ) ) ss << std::hex << b.manufactureDate();
+ else ss << std::hex << NA_HEX; ss << " ";
+
+ if ( b.has( SerialNumber ) ) ss << std::dec << b.serialNumber();
+ else ss << std::dec << NA_DEC; ss << " ";
+
+ if ( b.has( ManufacturerName ) ) ss << b.manufacturerName();
+ else ss << std::dec << NA_STR; ss << " ";
+
+ if ( b.has( DeviceName ) ) ss << b.deviceName();
+ else ss << std::dec << NA_STR; ss << " ";
+
+ if ( b.has( DeviceChemistry ) ) ss << b.deviceChemistry();
+ else ss << std::dec << NA_STR; ss << " ";
+
+ if ( b.has( ManufacturerData ) ) ss << std::hex << b.manufacturerData();
+ else ss << std::hex << NA_HEX;
+
+ return ss.str();
+}
+
+bool
+SmartBattery::has( SmartBatteryDataField field ) const
+{
+ if ( (int)field >= (int)(has_.size()) ) {
+ cout << "has(): field=" << field << ", has_.size=" << has_.size() << endl;
+ }
+ assert( (int)field < (int)(has_.size()) );
+ return has_[field];
+};
+
+}
Added: gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.h
===================================================================
--- gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.h (rev 0)
+++ gearbox/trunk/submitted/gbxsmartbatteryacfr/smartbattery.h 2008-06-25 07:27:56 UTC (rev 213)
@@ -0,0 +1,223 @@
+/*
+ * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
+ * http://gearbox.sf.net/
+ * Copyright (c) 2004-2008 Tobias Kaupp
+ *
+ * This distribution is licensed to you under the terms described in
+ * the LICENSE file included in this distribution.
+ *
+ */
+
+#ifndef SMARTBATTERY_H
+#define SMARTBATTERY_H
+
+#include <vector>
+#include <string>
+#include <assert.h>
+
+namespace gbxsmartbatteryacfr {
+
+//! Smart battery data specification
+//! Table of fields can be found at http://sbs-forum.org/specs/
+enum SmartBatteryDataField
+{
+ ManufacturerAccess = 0,
+ RemainingCapacityAlarm,
+ RemainingTimeAlarm,
+ BatteryMode,
+ AtRate,
+ AtRateTimeToFull,
+ AtRateTimeToEmpty,
+ AtRateOk,
+ Temperature,
+ Voltage,
+ Current,
+ AverageCurrent,
+ MaxError,
+ RelativeStateOfCharge,
+ AbsoluteStateOfCharge,
+ RemainingCapacity,
+ FullChargeCapacity,
+ RunTimeToEmpty,
+ AverageTimeToEmpty,
+ AverageTimeToFull,
+ ChargingCurrent,
+ ChargingVoltage,
+ BatteryStatus,
+ CycleCount,
+ DesignCapacity,
+ DesignVoltage,
+ SpecificationInfo,
+ ManufactureDate,
+ SerialNumber,
+ ManufacturerName,
+ DeviceName,
+ DeviceChemistry,
+ ManufacturerData,
+ NUM_SMARTBATTERY_FIELDS
+};
+
+//! Converts a string to a SmartBatteryDataField, returns NUM_SMARTBATTERY_FIELDS if string is not valid
+SmartBatteryDataField stringToSmartField( const std::string &fieldStr );
+
+//! SmartBattery class holds all the data of a single smart battery
+//! Since not all data is always present, access to data needs to be done as follows:
+//! if (has(Temperature)) { myTemp = smartBattery.temperature(); }
+class SmartBattery
+{
+ public:
+ SmartBattery() : has_(NUM_SMARTBATTERY_FIELDS)
+ { std::fill( has_.begin(), has_.end(), false ); };
+
+ bool has( SmartBatteryDataField field ) const;
+
+ uint16_t manufacturerAccess() const { assert(has_[ManufacturerAccess]); return manufacturerAccess_; };
+ void setManufacturerAccess( uint16_t manufacturerAccess ) { has_[ManufacturerAccess] = true; manufacturerAccess_ = manufacturerAccess; };
+
+ int remainingCapacityAlarm() const { assert(has_[RemainingCapacityAlarm]); return remainingCapacityAlarm_; };
+ void setRemainingCapacityAlarm( int remainingCapacityAlarm ) { has_[RemainingCapacityAlarm] = true; remainingCapacityAlarm_ = remainingCapacityAlarm; };
+
+ int remainingTimeAlarm() const { assert(has_[RemainingTimeAlarm]); return remainingTimeAlarm_; };
+ void setRemainingTimeAlarm( int remainingTimeAlarm ) { has_[RemainingTimeAlarm] = true; remainingTimeAlarm_ = remainingTimeAlarm; };
+
+ uint16_t batteryMode() const { assert(has_[BatteryMode]); return batteryMode_; };
+ void setBatteryMode( uint16_t batteryMode ) { has_[BatteryMode] = true; batteryMode_ = batteryMode; };
+
+ int atRate() const { assert(has_[AtRate]); return atRate_; };
+ void setAtRate( int atRate ) { has_[AtRate] = true; atRate_ = atRate; };
+
+ int atRateTimeToFull() const { assert(has_[AtRateTimeToFull]); return atRateTimeToFull_; };
+ void setAtRateTimeToFull( int atRateTimeToFull ) { has_[AtRateTimeToFull] = true; atRateTimeToFull_ = atRateTimeToFull; };
+
+ int atRateTimeToEmpty() const { assert(has_[AtRateTimeToEmpty]); return atRateTimeToEmpty_; };
+ void setAtRateTimeToEmpty( int atRateTimeToEmpty ) { has_[AtRateTimeToEmpty] = true; atRateTimeToEmpty_ = atRateTimeToEmpty; };
+
+ bool atRateOk() const { assert(has_[AtRateOk]); return atRateOk_; };
+ void setAtRateOk( bool atRateOk ) { has_[AtRateOk] = true; atRateOk_ = atRateOk; };
+
+ double temperature() const { assert(has_[Temperature]); return temperature_; };
+ void setTemperature( double temperature ) { has_[Temperature] = true; temperature_ = temperature; };
+
+ double voltage() const { assert(has_[Voltage]); return voltage_; };
+ void setVoltage( double voltage ) { has_[Voltage] = true; voltage_ = voltage; };
+
+ double current() const { assert(has_[Current]); return current_; };
+ void setCurrent( double current ) { has_[Current] = true; current_ = current; };
+
+ double averageCurrent() const { assert(has_[AverageCurrent]); return averageCurrent_; };
+ void setAverageCurrent( double averageCurrent ) { has_[AverageCurrent] = true; averageCurrent_ = averageCurrent; };
+
+ int maxError() const { assert(has_[MaxError]); return maxError_; };
+ void setMaxError( int maxError ) { has_[MaxError] = true; maxError_ = maxError; };
+
+ int relativeStateOfCharge() const { assert(has_[RelativeStateOfCharge]); return relativeStateOfCharge_; };
+ void setRelativeStateOfCharge( int relativeStateOfCharge ) { has_[RelativeStateOfCharge] = true; relativeStateOfCharge_ = relativeStateOfCharge; };
+
+ int absoluteStateOfCharge() const { assert(has_[AbsoluteStateOfCharge]); return absoluteStateOfCharge_; };
+ void setAbsoluteStateOfCharge( int absoluteStateOfCharge ) { has_[AbsoluteStateOfCharge] = true; absoluteStateOfCharge_ = absoluteStateOfCharge; };
+
+ int remainingCapacity() const { assert(has_[RemainingCapacity]); return remainingCapacity_; };
+ void setRemainingCapacity( int remainingCapacity ) { has_[RemainingCapacity] = true; remainingCapacity_ = remainingCapacity; };
+
+ int fullChargeCapacity() const { assert(has_[FullChargeCapacity]); return fullChargeCapacity_; };
+ void setFullChargeCapacity( int fullChargeCapacity ) { has_[FullChargeCapacity] = true; fullChargeCapacity_ = fullChargeCapacity; };
+
+ int runTimeToEmpty() const { assert(has_[RunTimeToEmpty]); return runTimeToEmpty_; };
+ void setRunTimeToEmpty( int runTimeToEmpty ) { has_[RunTimeToEmpty] = true; runTimeToEmpty_ = runTimeToEmpty; };
+
+ int averageTimeToEmpty() const { assert(has_[AverageTimeToEmpty]); return averageTimeToEmpty_; };
+ void setAverageTimeToEmpty( int averageTimeToEmpty ) { has_[AverageTimeToEmpty] = true; averageTimeToEmpty_ = averageTimeToEmpty; };
+
+ int averageTimeToFull() const { assert(has_[AverageTimeToFull]); return averageTimeToFull_; };
+ void setAverageTimeToFull( int averageTimeToFull ) { has_[AverageTimeToFull] = true; averageTimeToFull_ = averageTimeToFull; };
+
+ double chargingCurrent() const { assert(has_[ChargingCurrent]); return chargingCurrent_; };
+ void setChargingCurrent( double chargingCurrent ) { has_[ChargingCurrent] = true; chargingCurrent_ = chargingCurrent; };
+
+ double chargingVoltage() const { assert(has_[ChargingVoltage]); return chargingVoltage_; };
+ void setChargingVoltage( double chargingVoltage ) { has_[ChargingVoltage] = true; chargingVoltage_ = chargingVoltage; };
+
+ uint16_t batteryStatus() const { assert(has_[BatteryStatus]); return batteryStatus_; };
+ void setBatteryStatus( uint16_t batteryStatus ) { has_[BatteryStatus] = true; batteryStatus_ = batteryStatus; };
+
+ int cycleCount() const { assert(has_[CycleCount]); return cycleCount_; };
+ void setCycleCount( int cycleCount ) { has_[CycleCount] = true; cycleCount_ = cycleCount; };
+
+ int designCapacity() const { assert(has_[DesignCapacity]); return designCapacity_; };
+ void setDesignCapacity( int designCapacity ) { has_[DesignCapacity] = true; designCapacity_ = designCapacity; };
+
+ double designVoltage() const { assert(has_[DesignVoltage]); return designVoltage_; };
+ void setDesignVoltage( double designVoltage ) { has_[DesignVoltage] = true; designVoltage_ = designVoltage; };
+
+ uint16_t specificationInfo() const { assert(has_[SpecificationInfo]); return specificationInfo_; };
+ void setSpecificationInfo( uint16_t specificationInfo ) { has_[SpecificationInfo] = true; specificationInfo_ = specificationInfo; };
+
+ ui...
[truncated message content] |