battery_monitor_treeview.cpp

00001 
00002 /***************************************************************************
00003  *  battery_monitor_treeview.cpp - TreeView class for displaying the battery
00004  *                                 status of the robots
00005  *
00006  *  Created: Mon Apr 06 16:08:50 2009
00007  *  Copyright  2009  Daniel Beck
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL file in the doc directory.
00022  */
00023 
00024 #include "battery_monitor_treeview.h"
00025 
00026 #include <blackboard/remote.h>
00027 #include <gui_utils/interface_dispatcher.h>
00028 #include <interfaces/BatteryInterface.h>
00029 
00030 #include <cstring>
00031 
00032 using namespace std;
00033 using namespace fawkes;
00034 
00035 /** @class BatteryMonitorTreeView tools/battery_monitor/battery_monitor_treeview.h
00036  * A treeview that retrieves battery data from the robots over remote
00037  * blackboard connections and displays those.
00038  * @author Daniel Beck
00039  */
00040 
00041 /** @class BatteryMonitorTreeView::BatteryRecord tools/battery_monitor/battery_monitor_treeview.h
00042  * Column record class for the battery monitor treeview.
00043  * @author Daniel Beck
00044  */
00045 
00046 /** @var BatteryMonitorTreeView::m_battery_record
00047  * Column record object to acces the columns of the storage object.
00048  */
00049 
00050 /** @var BatteryMonitorTreeView::m_battery_list
00051  * Storage object.
00052  */
00053 
00054 /** @var BatteryMonitorTreeView::m_remote_bbs
00055  * Map with remote blackboards: hostname -> remote blackboard.
00056  */
00057 
00058 /** @var BatteryMonitorTreeView::m_battery_interfaces
00059  * Map containing the battery interfaces: hostname -> battery interface
00060  */
00061 
00062 /** @var BatteryMonitorTreeView::m_interface_dispatcher
00063  * Interface dispatcher for the battery interfaces.
00064  */
00065 
00066 /** Constructor.
00067  * @param cobject base object type
00068  * @param ref_xml Glade XML object
00069  */
00070 BatteryMonitorTreeView::BatteryMonitorTreeView( BaseObjectType* cobject,
00071                                                 const Glib::RefPtr< Gnome::Glade::Xml >& ref_xml )
00072   : Gtk::TreeView( cobject )
00073 {
00074   m_battery_list = Gtk::ListStore::create( m_battery_record );
00075   set_model( m_battery_list );
00076 
00077   append_column( "Host", m_battery_record.short_name );
00078   append_column_numeric( "Abs. SOC [%]", m_battery_record.absolute_soc, "%.1f" ); 
00079   append_column_numeric( "Rel. SOC [%]", m_battery_record.relative_soc, "%.1f" ); 
00080   append_column_numeric( "Voltage [V]", m_battery_record.voltage, "%.3f" );
00081   append_column_numeric( "Current [A]", m_battery_record.current, "%.3f" );
00082 
00083   ref_xml->get_widget("dlgWarning", m_dlg_warning);
00084   m_dlg_warning->hide();
00085 
00086   m_trigger_update.connect( sigc::mem_fun( *this, &BatteryMonitorTreeView::update ) );
00087 
00088   m_relative_soc_threshold = 20.0;
00089 }
00090 
00091 /** Destructor. */
00092 BatteryMonitorTreeView::~BatteryMonitorTreeView()
00093 {
00094   for ( std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.begin();
00095         biit != m_battery_interfaces.end();
00096         ++biit )
00097   {
00098     std::map< string, BlackBoard* >::iterator rbit;
00099     rbit = m_remote_bbs.find( biit->first );
00100     
00101     std::map< string, InterfaceDispatcher* >::iterator idit;
00102     idit = m_interface_dispatcher.find( biit->first );
00103 
00104     if ( rbit != m_remote_bbs.end() )
00105     {
00106       rbit->second->unregister_listener( idit->second );
00107       rbit->second->close( biit->second );
00108       delete rbit->second;
00109     }
00110   }
00111 
00112   // delete interface dispatcher
00113   for ( std::map< string, InterfaceDispatcher* >::iterator i = m_interface_dispatcher.begin();
00114         i != m_interface_dispatcher.end();
00115         ++i )
00116   {
00117     delete i->second;
00118   }
00119 
00120   // delete remote blackboards
00121   for ( std::map< string, BlackBoard* >::iterator i = m_remote_bbs.begin();
00122         i != m_remote_bbs.end();
00123         ++i )
00124   {
00125     delete i->second;
00126   }
00127 
00128   delete m_dlg_warning;
00129 }
00130 
00131 /** Add given host.
00132  * @param h the host's hostname
00133  */
00134 void
00135 BatteryMonitorTreeView::add_host( const char* h )
00136 {
00137   string host(h);
00138 
00139   BlackBoard* rbb;
00140   std::map< string, BlackBoard* >::iterator i = m_remote_bbs.find( host );
00141 
00142   if ( i == m_remote_bbs.end() )
00143     // no remote blackboard opened, yet
00144   {
00145     try
00146     { 
00147       rbb = new RemoteBlackBoard( h, 1910 );
00148       m_remote_bbs[ host ] = rbb;
00149     }
00150     catch ( Exception& e )
00151     {
00152       e.append( "Could not open remote blackboard on host %s", h );
00153       e.print_trace();
00154       return;
00155     }
00156   }
00157   else
00158   { rbb = i->second; }
00159 
00160   if ( m_battery_interfaces.find( host ) == m_battery_interfaces.end() )
00161     // no battery interface opened, yet
00162   {
00163     try
00164     {
00165       BatteryInterface* bi;
00166       bi = rbb->open_for_reading< BatteryInterface >( "Battery" );
00167       m_battery_interfaces[ host ] = bi;
00168 
00169       InterfaceDispatcher* id = new InterfaceDispatcher( "BatteryMonitorTreeView", bi );
00170 
00171       id->signal_data_changed().connect( sigc::mem_fun( *this,
00172                                                         &BatteryMonitorTreeView::on_data_changed ) );
00173       id->signal_writer_added().connect( sigc::mem_fun( *this,
00174                                                         &BatteryMonitorTreeView::on_writer_added ) );
00175       id->signal_writer_removed().connect( sigc::mem_fun( *this,
00176                                                           &BatteryMonitorTreeView::on_writer_removed ) );
00177       rbb->register_listener( id, BlackBoard::BBIL_FLAG_DATA || BlackBoard::BBIL_FLAG_WRITER );
00178     }
00179     catch ( Exception& e )
00180     {
00181       e.append( "Opening battery interface on host %s failed", h );
00182       e.print_trace();
00183     }
00184 
00185     // add below threshold counter
00186     m_below_threshold_counter[ host ] = 0;
00187   }
00188   
00189   m_trigger_update();
00190 }
00191 
00192 /** Remove given host.
00193  * @param h the host's hostname
00194  */
00195 void
00196 BatteryMonitorTreeView::rem_host( const char* h )
00197 {
00198   string host( h );
00199 
00200   std::map< string, BlackBoard* >::iterator rbbit = m_remote_bbs.find( host );
00201   if ( m_remote_bbs.end() == rbbit )
00202     // no blackboard opened---nothing to do
00203   { return; }
00204 
00205   std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.find( host );
00206 
00207   if ( m_battery_interfaces.end() != biit )
00208     // battery inteface opened. listener need to be unregistered and
00209     // interface nees to be closed
00210   {
00211     try
00212     {
00213       BlackBoard* rbb = rbbit->second;
00214       InterfaceDispatcher* id = m_interface_dispatcher.find( host )->second;
00215       rbb->unregister_listener( id );
00216       rbb->close( biit->second );
00217       m_battery_interfaces.erase( biit );
00218     }
00219     catch ( Exception& e )
00220     {
00221       e.append( "Closing battery interface for host %s could not be closed", h );
00222       e.print_trace();
00223     }
00224   }
00225 
00226   // destroy blackboard
00227   delete rbbit->second;
00228   m_remote_bbs.erase( rbbit );
00229 
00230   // remove below threshold counter
00231   m_below_threshold_counter.erase( host );
00232 
00233   m_trigger_update();
00234 }
00235 
00236 void
00237 BatteryMonitorTreeView::update()
00238 {
00239   // clear treeview
00240   Gtk::TreeModel::Children::iterator rit = m_battery_list->children().begin();
00241   while ( rit != m_battery_list->children().end() )
00242   {
00243     rit = m_battery_list->erase( rit );
00244   }
00245 
00246   for ( std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.begin();
00247         biit != m_battery_interfaces.end();
00248         ++biit )
00249   {
00250     // update data in interface
00251     BatteryInterface* bi = biit->second;
00252 
00253     try
00254     {
00255       bi->read();
00256     }
00257     catch ( Exception& e )
00258     {
00259       e.append( "read() failed" );
00260       e.print_trace();
00261       continue;
00262     }
00263 
00264     if ( !bi->has_writer() )
00265       // only consider interfaces which have a writer
00266     { continue; }
00267 
00268     Gtk::TreeModel::Row row;
00269     row = *m_battery_list->append();
00270     row[ m_battery_record.fqdn ] = Glib::ustring( biit->first );
00271     
00272     char* fqdn = strdup( (biit->first).c_str() );
00273     char* sh;
00274     char delim = '.';
00275     sh = strtok( fqdn, &delim );
00276     int i = atoi( sh );
00277     
00278     if ( 0 != i )
00279     { row[ m_battery_record.short_name ] = Glib::ustring( biit->first ); }
00280     else
00281     { row[ m_battery_record.short_name ] = Glib::ustring( sh ); }
00282     
00283     row[ m_battery_record.absolute_soc ] = bi->absolute_soc() * 100.0;
00284     row[ m_battery_record.relative_soc ] = bi->relative_soc() * 100.0;
00285     row[ m_battery_record.current ] = bi->current() / 1000.0;
00286     row[ m_battery_record.voltage ] = bi->voltage() / 1000.0;
00287 
00288     string fqdn_str = string( fqdn );
00289     if ( row[ m_battery_record.relative_soc ] <= m_relative_soc_threshold )
00290     {
00291       unsigned int cnt = m_below_threshold_counter[ fqdn_str ];
00292       m_below_threshold_counter[ fqdn_str ] = ++cnt;
00293     }
00294     else
00295     { m_below_threshold_counter[ fqdn_str ] = 0; }
00296 
00297     free(fqdn);
00298   }
00299   
00300   Glib::ustring secondary = "The batteries on ";
00301   bool below_threshold = false;
00302 
00303   for ( std::map< string, unsigned int >::iterator i = m_below_threshold_counter.begin();
00304         i != m_below_threshold_counter.end();
00305         ++i )
00306   {
00307     if ( i->second > 2 )
00308     {
00309       secondary += "<b>" + Glib::ustring( (i->first).c_str() ) + "</b>" + " ";
00310       i->second = 0;
00311 
00312       below_threshold = true;
00313     }
00314   }
00315   secondary += "need to be replaced.";
00316 
00317   if ( below_threshold )
00318   {
00319     m_dlg_warning->set_secondary_text( secondary, true );
00320     m_dlg_warning->set_urgency_hint();
00321     m_dlg_warning->run();
00322     m_dlg_warning->hide();
00323   }
00324 }
00325 
00326 void
00327 BatteryMonitorTreeView::on_data_changed( fawkes::Interface* interface )
00328 {
00329   update();
00330 }
00331 
00332 void
00333 BatteryMonitorTreeView::on_writer_added( fawkes::Interface* interface )
00334 {
00335   update();
00336 }
00337 
00338 void
00339 BatteryMonitorTreeView::on_writer_removed( fawkes::Interface* interface )
00340 {
00341   update();
00342 }

Generated on Tue Feb 22 13:31:30 2011 for Fawkes API by  doxygen 1.4.7