Fawkes API  Fawkes Development Version
battery_monitor_treeview.cpp
1 
2 /***************************************************************************
3  * battery_monitor_treeview.cpp - TreeView class for displaying the battery
4  * status of the robots
5  *
6  * Created: Mon Apr 06 16:08:50 2009
7  * Copyright 2009 Daniel Beck
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL file in the doc directory.
22  */
23 
24 #include "battery_monitor_treeview.h"
25 
26 #include <blackboard/remote.h>
27 #include <gui_utils/interface_dispatcher.h>
28 #include <interfaces/BatteryInterface.h>
29 
30 #include <cstring>
31 
32 using namespace std;
33 using namespace fawkes;
34 
35 /** @class BatteryMonitorTreeView tools/battery_monitor/battery_monitor_treeview.h
36  * A treeview that retrieves battery data from the robots over remote
37  * blackboard connections and displays those.
38  * @author Daniel Beck
39  */
40 
41 /** @class BatteryMonitorTreeView::BatteryRecord tools/battery_monitor/battery_monitor_treeview.h
42  * Column record class for the battery monitor treeview.
43  * @author Daniel Beck
44  */
45 
46 /** @var BatteryMonitorTreeView::m_battery_record
47  * Column record object to acces the columns of the storage object.
48  */
49 
50 /** @var BatteryMonitorTreeView::m_battery_list
51  * Storage object.
52  */
53 
54 /** @var BatteryMonitorTreeView::m_remote_bbs
55  * Map with remote blackboards: hostname -> remote blackboard.
56  */
57 
58 /** @var BatteryMonitorTreeView::m_battery_interfaces
59  * Map containing the battery interfaces: hostname -> battery interface
60  */
61 
62 /** @var BatteryMonitorTreeView::m_interface_dispatcher
63  * Interface dispatcher for the battery interfaces.
64  */
65 
66 /** Constructor.
67  * @param cobject base object type
68  * @param builder builder to get widgets from
69  */
71  const Glib::RefPtr<Gtk::Builder> &builder)
72  : Gtk::TreeView( cobject )
73 {
74  m_battery_list = Gtk::ListStore::create( m_battery_record );
75  set_model( m_battery_list );
76 
77  append_column( "Host", m_battery_record.short_name );
78  append_column_numeric( "Abs. SOC [%]", m_battery_record.absolute_soc, "%.1f" );
79  append_column_numeric( "Rel. SOC [%]", m_battery_record.relative_soc, "%.1f" );
80  append_column_numeric( "Voltage [V]", m_battery_record.voltage, "%.3f" );
81  append_column_numeric( "Current [A]", m_battery_record.current, "%.3f" );
82 
83  builder->get_widget("dlgWarning", m_dlg_warning);
84  m_dlg_warning->hide();
85 
86  m_trigger_update.connect(sigc::mem_fun(*this, &BatteryMonitorTreeView::update));
87 
88  m_relative_soc_threshold = 20.0;
89 }
90 
91 /** Destructor. */
93 {
94  std::map< string, BatteryInterface* >::iterator biit;
95  for (biit = m_battery_interfaces.begin();
96  biit != m_battery_interfaces.end();
97  ++biit)
98  {
99  std::map< string, BlackBoard* >::iterator rbit;
100  rbit = m_remote_bbs.find( biit->first );
101 
102  std::map< string, InterfaceDispatcher* >::iterator idit;
103  idit = m_interface_dispatcher.find( biit->first );
104 
105  if ( rbit != m_remote_bbs.end() )
106  {
107  rbit->second->unregister_listener( idit->second );
108  rbit->second->close( biit->second );
109  delete rbit->second;
110  }
111  }
112 
113  // delete interface dispatcher
114  std::map< string, InterfaceDispatcher* >::iterator i;
115  for (i = m_interface_dispatcher.begin();
116  i != m_interface_dispatcher.end();
117  ++i )
118  {
119  delete i->second;
120  }
121 
122  // delete remote blackboards
123  for ( std::map< string, BlackBoard* >::iterator i = m_remote_bbs.begin();
124  i != m_remote_bbs.end();
125  ++i )
126  {
127  delete i->second;
128  }
129 
130  delete m_dlg_warning;
131 }
132 
133 /** Add given host.
134  * @param h the host's hostname
135  */
136 void
138 {
139  string host(h);
140 
141  BlackBoard* rbb;
142  std::map< string, BlackBoard* >::iterator i = m_remote_bbs.find( host );
143 
144  if ( i == m_remote_bbs.end() )
145  // no remote blackboard opened, yet
146  {
147  try
148  {
149  rbb = new RemoteBlackBoard( h, 1910 );
150  m_remote_bbs[ host ] = rbb;
151  }
152  catch ( Exception& e )
153  {
154  e.append( "Could not open remote blackboard on host %s", h );
155  e.print_trace();
156  return;
157  }
158  }
159  else
160  { rbb = i->second; }
161 
162  if ( m_battery_interfaces.find( host ) == m_battery_interfaces.end() )
163  // no battery interface opened, yet
164  {
165  try
166  {
167  BatteryInterface* bi;
168  bi = rbb->open_for_reading< BatteryInterface >( "Battery" );
169  m_battery_interfaces[ host ] = bi;
170 
171  InterfaceDispatcher* id =
172  new InterfaceDispatcher( "BatteryMonitorTreeView", bi );
173 
174  id->signal_data_changed().connect( sigc::mem_fun( *this,
175  &BatteryMonitorTreeView::on_data_changed ) );
176  id->signal_writer_added().connect( sigc::mem_fun( *this,
177  &BatteryMonitorTreeView::on_writer_added ) );
178  id->signal_writer_removed().connect( sigc::mem_fun( *this,
179  &BatteryMonitorTreeView::on_writer_removed ) );
180  rbb->register_listener( id, BlackBoard::BBIL_FLAG_DATA | BlackBoard::BBIL_FLAG_WRITER );
181  }
182  catch ( Exception& e )
183  {
184  e.append( "Opening battery interface on host %s failed", h );
185  e.print_trace();
186  }
187 
188  // add below threshold counter
189  m_below_threshold_counter[ host ] = 0;
190  }
191 
192  m_trigger_update();
193 }
194 
195 /** Remove given host.
196  * @param h the host's hostname
197  */
198 void
200 {
201  string host( h );
202 
203  std::map< string, BlackBoard* >::iterator rbbit = m_remote_bbs.find( host );
204  if ( m_remote_bbs.end() == rbbit )
205  // no blackboard opened---nothing to do
206  { return; }
207 
208  std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.find( host );
209 
210  if ( m_battery_interfaces.end() != biit )
211  // battery inteface opened. listener need to be unregistered and
212  // interface nees to be closed
213  {
214  try
215  {
216  BlackBoard* rbb = rbbit->second;
217  InterfaceDispatcher* id = m_interface_dispatcher.find( host )->second;
218  rbb->unregister_listener( id );
219  rbb->close( biit->second );
220  m_battery_interfaces.erase( biit );
221  }
222  catch ( Exception& e )
223  {
224  e.append( "Closing battery interface for host %s could not be closed", h );
225  e.print_trace();
226  }
227  }
228 
229  // destroy blackboard
230  delete rbbit->second;
231  m_remote_bbs.erase( rbbit );
232 
233  // remove below threshold counter
234  m_below_threshold_counter.erase( host );
235 
236  m_trigger_update();
237 }
238 
239 void
240 BatteryMonitorTreeView::update()
241 {
242  // clear treeview
243  Gtk::TreeModel::Children::iterator rit = m_battery_list->children().begin();
244  while ( rit != m_battery_list->children().end() )
245  {
246  rit = m_battery_list->erase( rit );
247  }
248 
249  for ( std::map< string, BatteryInterface* >::iterator biit = m_battery_interfaces.begin();
250  biit != m_battery_interfaces.end();
251  ++biit )
252  {
253  // update data in interface
254  BatteryInterface* bi = biit->second;
255 
256  try
257  {
258  bi->read();
259  }
260  catch ( Exception& e )
261  {
262  e.append( "read() failed" );
263  e.print_trace();
264  continue;
265  }
266 
267  if ( !bi->has_writer() )
268  // only consider interfaces which have a writer
269  { continue; }
270 
271  Gtk::TreeModel::Row row;
272  row = *m_battery_list->append();
273  row[ m_battery_record.fqdn ] = Glib::ustring( biit->first );
274 
275  char* fqdn = strdup( (biit->first).c_str() );
276  char* sh;
277  char delim = '.';
278  sh = strtok( fqdn, &delim );
279  int i = atoi( sh );
280 
281  if ( 0 != i )
282  { row[ m_battery_record.short_name ] = Glib::ustring( biit->first ); }
283  else
284  { row[ m_battery_record.short_name ] = Glib::ustring( sh ); }
285 
286  row[ m_battery_record.absolute_soc ] = bi->absolute_soc() * 100.0;
287  row[ m_battery_record.relative_soc ] = bi->relative_soc() * 100.0;
288  row[ m_battery_record.current ] = bi->current() / 1000.0;
289  row[ m_battery_record.voltage ] = bi->voltage() / 1000.0;
290 
291  string fqdn_str = string( fqdn );
292  if ( row[ m_battery_record.relative_soc ] <= m_relative_soc_threshold )
293  {
294  unsigned int cnt = m_below_threshold_counter[ fqdn_str ];
295  m_below_threshold_counter[ fqdn_str ] = ++cnt;
296  }
297  else
298  { m_below_threshold_counter[ fqdn_str ] = 0; }
299 
300  free(fqdn);
301  }
302 
303  Glib::ustring secondary = "The batteries on ";
304  bool below_threshold = false;
305 
306  for ( std::map< string, unsigned int >::iterator i = m_below_threshold_counter.begin();
307  i != m_below_threshold_counter.end();
308  ++i )
309  {
310  if ( i->second > 2 )
311  {
312  secondary += "<b>" + Glib::ustring( (i->first).c_str() ) + "</b>" + " ";
313  i->second = 0;
314 
315  below_threshold = true;
316  }
317  }
318  secondary += "need to be replaced.";
319 
320  if ( below_threshold )
321  {
322  m_dlg_warning->set_secondary_text( secondary, true );
323  m_dlg_warning->set_urgency_hint();
324  m_dlg_warning->run();
325  m_dlg_warning->hide();
326  }
327 }
328 
329 void
330 BatteryMonitorTreeView::on_data_changed( fawkes::Interface* interface )
331 {
332  update();
333 }
334 
335 void
336 BatteryMonitorTreeView::on_writer_added( fawkes::Interface* interface )
337 {
338  update();
339 }
340 
341 void
342 BatteryMonitorTreeView::on_writer_removed( fawkes::Interface* interface )
343 {
344  update();
345 }
float relative_soc() const
Get relative_soc value.
std::map< std::string, fawkes::InterfaceDispatcher *> m_interface_dispatcher
Interface dispatcher for the battery interfaces.
uint32_t voltage() const
Get voltage value.
void rem_host(const char *host)
Remove given host.
Fawkes library namespace.
BatteryInterface Fawkes BlackBoard Interface.
STL namespace.
float absolute_soc() const
Get absolute_soc value.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:218
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
Gtk::TreeModelColumn< Glib::ustring > short_name
A shorter hostname (w/o domain)
uint32_t current() const
Get current value.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:190
Base class for exceptions in Fawkes.
Definition: exception.h:36
BatteryMonitorTreeView(BaseObjectType *cobject, const Glib::RefPtr< Gtk::Builder > &builder)
Constructor.
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:477
Gtk::TreeModelColumn< Glib::ustring > fqdn
The FQDN.
Gtk::TreeModelColumn< float > relative_soc
The battery&#39;s relative state of charge.
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:834
BatteryRecord m_battery_record
Column record object to acces the columns of the storage object.
Gtk::TreeModelColumn< float > voltage
The battery&#39;s voltage.
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
Remote BlackBoard.
Definition: remote.h:48
Gtk::TreeModelColumn< float > current
The battery&#39;s current.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
std::map< std::string, fawkes::BatteryInterface *> m_battery_interfaces
Map containing the battery interfaces: hostname -> battery interface.
virtual ~BatteryMonitorTreeView()
Destructor.
The BlackBoard abstract class.
Definition: blackboard.h:48
void add_host(const char *host)
Add given host.
Gtk::TreeModelColumn< float > absolute_soc
The battery&#39;s absolute state of charge.
Interface listener with dispatcher.
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
Glib::RefPtr< Gtk::ListStore > m_battery_list
Storage object.
std::map< std::string, fawkes::BlackBoard *> m_remote_bbs
Map with remote blackboards: hostname -> remote blackboard.
virtual void close(Interface *interface)=0
Close interface.