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 builder builder to get widgets from 00069 */ 00070 BatteryMonitorTreeView::BatteryMonitorTreeView(BaseObjectType* cobject, 00071 const Glib::RefPtr<Gtk::Builder> &builder) 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 builder->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 std::map< string, BatteryInterface* >::iterator biit; 00095 for (biit = m_battery_interfaces.begin(); 00096 biit != m_battery_interfaces.end(); 00097 ++biit) 00098 { 00099 std::map< string, BlackBoard* >::iterator rbit; 00100 rbit = m_remote_bbs.find( biit->first ); 00101 00102 std::map< string, InterfaceDispatcher* >::iterator idit; 00103 idit = m_interface_dispatcher.find( biit->first ); 00104 00105 if ( rbit != m_remote_bbs.end() ) 00106 { 00107 rbit->second->unregister_listener( idit->second ); 00108 rbit->second->close( biit->second ); 00109 delete rbit->second; 00110 } 00111 } 00112 00113 // delete interface dispatcher 00114 std::map< string, InterfaceDispatcher* >::iterator i; 00115 for (i = m_interface_dispatcher.begin(); 00116 i != m_interface_dispatcher.end(); 00117 ++i ) 00118 { 00119 delete i->second; 00120 } 00121 00122 // delete remote blackboards 00123 for ( std::map< string, BlackBoard* >::iterator i = m_remote_bbs.begin(); 00124 i != m_remote_bbs.end(); 00125 ++i ) 00126 { 00127 delete i->second; 00128 } 00129 00130 delete m_dlg_warning; 00131 } 00132 00133 /** Add given host. 00134 * @param h the host's hostname 00135 */ 00136 void 00137 BatteryMonitorTreeView::add_host( const char* h ) 00138 { 00139 string host(h); 00140 00141 BlackBoard* rbb; 00142 std::map< string, BlackBoard* >::iterator i = m_remote_bbs.find( host ); 00143 00144 if ( i == m_remote_bbs.end() ) 00145 // no remote blackboard opened, yet 00146 { 00147 try 00148 { 00149 rbb = new RemoteBlackBoard( h, 1910 ); 00150 m_remote_bbs[ host ] = rbb; 00151 } 00152 catch ( Exception& e ) 00153 { 00154 e.append( "Could not open remote blackboard on host %s", h ); 00155 e.print_trace(); 00156 return; 00157 } 00158 } 00159 else 00160 { rbb = i->second; } 00161 00162 if ( m_battery_interfaces.find( host ) == m_battery_interfaces.end() ) 00163 // no battery interface opened, yet 00164 { 00165 try 00166 { 00167 BatteryInterface* bi; 00168 bi = rbb->open_for_reading< BatteryInterface >( "Battery" ); 00169 m_battery_interfaces[ host ] = bi; 00170 00171 InterfaceDispatcher* id = 00172 new InterfaceDispatcher( "BatteryMonitorTreeView", bi ); 00173 00174 id->signal_data_changed().connect( sigc::mem_fun( *this, 00175 &BatteryMonitorTreeView::on_data_changed ) ); 00176 id->signal_writer_added().connect( sigc::mem_fun( *this, 00177 &BatteryMonitorTreeView::on_writer_added ) ); 00178 id->signal_writer_removed().connect( sigc::mem_fun( *this, 00179 &BatteryMonitorTreeView::on_writer_removed ) ); 00180 rbb->register_listener( id, BlackBoard::BBIL_FLAG_DATA | BlackBoard::BBIL_FLAG_WRITER ); 00181 } 00182 catch ( Exception& e ) 00183 { 00184 e.append( "Opening battery interface on host %s failed", h ); 00185 e.print_trace(); 00186 } 00187 00188 // add below threshold counter 00189 m_below_threshold_counter[ host ] = 0; 00190 } 00191 00192 m_trigger_update(); 00193 } 00194 00195 /** Remove given host. 00196 * @param h the host's hostname 00197 */ 00198 void 00199 BatteryMonitorTreeView::rem_host( const char* h ) 00200 { 00201 string host( h ); 00202 00203 std::map< string, BlackBoard* >::iterator rbbit = m_remote_bbs.find( host ); 00204 if ( m_remote_bbs.end() == rbbit ) 00205 // no blackboard opened---nothing to do 00206 { return; } 00207 00208 std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.find( host ); 00209 00210 if ( m_battery_interfaces.end() != biit ) 00211 // battery inteface opened. listener need to be unregistered and 00212 // interface nees to be closed 00213 { 00214 try 00215 { 00216 BlackBoard* rbb = rbbit->second; 00217 InterfaceDispatcher* id = m_interface_dispatcher.find( host )->second; 00218 rbb->unregister_listener( id ); 00219 rbb->close( biit->second ); 00220 m_battery_interfaces.erase( biit ); 00221 } 00222 catch ( Exception& e ) 00223 { 00224 e.append( "Closing battery interface for host %s could not be closed", h ); 00225 e.print_trace(); 00226 } 00227 } 00228 00229 // destroy blackboard 00230 delete rbbit->second; 00231 m_remote_bbs.erase( rbbit ); 00232 00233 // remove below threshold counter 00234 m_below_threshold_counter.erase( host ); 00235 00236 m_trigger_update(); 00237 } 00238 00239 void 00240 BatteryMonitorTreeView::update() 00241 { 00242 // clear treeview 00243 Gtk::TreeModel::Children::iterator rit = m_battery_list->children().begin(); 00244 while ( rit != m_battery_list->children().end() ) 00245 { 00246 rit = m_battery_list->erase( rit ); 00247 } 00248 00249 for ( std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.begin(); 00250 biit != m_battery_interfaces.end(); 00251 ++biit ) 00252 { 00253 // update data in interface 00254 BatteryInterface* bi = biit->second; 00255 00256 try 00257 { 00258 bi->read(); 00259 } 00260 catch ( Exception& e ) 00261 { 00262 e.append( "read() failed" ); 00263 e.print_trace(); 00264 continue; 00265 } 00266 00267 if ( !bi->has_writer() ) 00268 // only consider interfaces which have a writer 00269 { continue; } 00270 00271 Gtk::TreeModel::Row row; 00272 row = *m_battery_list->append(); 00273 row[ m_battery_record.fqdn ] = Glib::ustring( biit->first ); 00274 00275 char* fqdn = strdup( (biit->first).c_str() ); 00276 char* sh; 00277 char delim = '.'; 00278 sh = strtok( fqdn, &delim ); 00279 int i = atoi( sh ); 00280 00281 if ( 0 != i ) 00282 { row[ m_battery_record.short_name ] = Glib::ustring( biit->first ); } 00283 else 00284 { row[ m_battery_record.short_name ] = Glib::ustring( sh ); } 00285 00286 row[ m_battery_record.absolute_soc ] = bi->absolute_soc() * 100.0; 00287 row[ m_battery_record.relative_soc ] = bi->relative_soc() * 100.0; 00288 row[ m_battery_record.current ] = bi->current() / 1000.0; 00289 row[ m_battery_record.voltage ] = bi->voltage() / 1000.0; 00290 00291 string fqdn_str = string( fqdn ); 00292 if ( row[ m_battery_record.relative_soc ] <= m_relative_soc_threshold ) 00293 { 00294 unsigned int cnt = m_below_threshold_counter[ fqdn_str ]; 00295 m_below_threshold_counter[ fqdn_str ] = ++cnt; 00296 } 00297 else 00298 { m_below_threshold_counter[ fqdn_str ] = 0; } 00299 00300 free(fqdn); 00301 } 00302 00303 Glib::ustring secondary = "The batteries on "; 00304 bool below_threshold = false; 00305 00306 for ( std::map< string, unsigned int >::iterator i = m_below_threshold_counter.begin(); 00307 i != m_below_threshold_counter.end(); 00308 ++i ) 00309 { 00310 if ( i->second > 2 ) 00311 { 00312 secondary += "<b>" + Glib::ustring( (i->first).c_str() ) + "</b>" + " "; 00313 i->second = 0; 00314 00315 below_threshold = true; 00316 } 00317 } 00318 secondary += "need to be replaced."; 00319 00320 if ( below_threshold ) 00321 { 00322 m_dlg_warning->set_secondary_text( secondary, true ); 00323 m_dlg_warning->set_urgency_hint(); 00324 m_dlg_warning->run(); 00325 m_dlg_warning->hide(); 00326 } 00327 } 00328 00329 void 00330 BatteryMonitorTreeView::on_data_changed( fawkes::Interface* interface ) 00331 { 00332 update(); 00333 } 00334 00335 void 00336 BatteryMonitorTreeView::on_writer_added( fawkes::Interface* interface ) 00337 { 00338 update(); 00339 } 00340 00341 void 00342 BatteryMonitorTreeView::on_writer_removed( fawkes::Interface* interface ) 00343 { 00344 update(); 00345 }