Fawkes API
Fawkes Development Version
|
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 }