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
32using namespace std;
33using 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(); biit != m_battery_interfaces.end(); ++biit) {
96 std::map<string, BlackBoard *>::iterator rbit;
97 rbit = m_remote_bbs.find(biit->first);
98
99 std::map<string, InterfaceDispatcher *>::iterator idit;
100 idit = m_interface_dispatcher.find(biit->first);
101
102 if (rbit != m_remote_bbs.end()) {
103 rbit->second->unregister_listener(idit->second);
104 rbit->second->close(biit->second);
105 delete rbit->second;
106 }
107 }
108
109 // delete interface dispatcher
110 std::map<string, InterfaceDispatcher *>::iterator i;
111 for (i = m_interface_dispatcher.begin(); i != m_interface_dispatcher.end(); ++i) {
112 delete i->second;
113 }
114
115 // delete remote blackboards
116 for (std::map<string, BlackBoard *>::iterator i = m_remote_bbs.begin(); i != m_remote_bbs.end();
117 ++i) {
118 delete i->second;
119 }
120
121 delete m_dlg_warning;
122}
123
124/** Add given host.
125 * @param h the host's hostname
126 */
127void
129{
130 string host(h);
131
132 BlackBoard * rbb;
133 std::map<string, BlackBoard *>::iterator i = m_remote_bbs.find(host);
134
135 if (i == m_remote_bbs.end())
136 // no remote blackboard opened, yet
137 {
138 try {
139 rbb = new RemoteBlackBoard(h, 1910);
140 m_remote_bbs[host] = rbb;
141 } catch (Exception &e) {
142 e.append("Could not open remote blackboard on host %s", h);
143 e.print_trace();
144 return;
145 }
146 } else {
147 rbb = i->second;
148 }
149
150 if (m_battery_interfaces.find(host) == m_battery_interfaces.end())
151 // no battery interface opened, yet
152 {
153 try {
155 bi = rbb->open_for_reading<BatteryInterface>("Battery");
156 m_battery_interfaces[host] = bi;
157
158 InterfaceDispatcher *id = new InterfaceDispatcher("BatteryMonitorTreeView", bi);
159
160 id->signal_data_changed().connect(
161 sigc::mem_fun(*this, &BatteryMonitorTreeView::on_data_changed));
162 id->signal_writer_added().connect(
163 sigc::mem_fun(*this, &BatteryMonitorTreeView::on_writer_added));
164 id->signal_writer_removed().connect(
165 sigc::mem_fun(*this, &BatteryMonitorTreeView::on_writer_removed));
166 rbb->register_listener(id, BlackBoard::BBIL_FLAG_DATA | BlackBoard::BBIL_FLAG_WRITER);
167 } catch (Exception &e) {
168 e.append("Opening battery interface on host %s failed", h);
169 e.print_trace();
170 }
171
172 // add below threshold counter
173 m_below_threshold_counter[host] = 0;
174 }
175
176 m_trigger_update();
177}
178
179/** Remove given host.
180 * @param h the host's hostname
181 */
182void
184{
185 string host(h);
186
187 std::map<string, BlackBoard *>::iterator rbbit = m_remote_bbs.find(host);
188 if (m_remote_bbs.end() == rbbit)
189 // no blackboard opened---nothing to do
190 {
191 return;
192 }
193
194 std::map<string, BatteryInterface *>::iterator biit = m_battery_interfaces.find(host);
195
196 if (m_battery_interfaces.end() != biit)
197 // battery inteface opened. listener need to be unregistered and
198 // interface nees to be closed
199 {
200 try {
201 BlackBoard * rbb = rbbit->second;
202 InterfaceDispatcher *id = m_interface_dispatcher.find(host)->second;
203 rbb->unregister_listener(id);
204 rbb->close(biit->second);
205 m_battery_interfaces.erase(biit);
206 } catch (Exception &e) {
207 e.append("Closing battery interface for host %s could not be closed", h);
208 e.print_trace();
209 }
210 }
211
212 // destroy blackboard
213 delete rbbit->second;
214 m_remote_bbs.erase(rbbit);
215
216 // remove below threshold counter
217 m_below_threshold_counter.erase(host);
218
219 m_trigger_update();
220}
221
222void
223BatteryMonitorTreeView::update()
224{
225 // clear treeview
226 Gtk::TreeModel::Children::iterator rit = m_battery_list->children().begin();
227 while (rit != m_battery_list->children().end()) {
228 rit = m_battery_list->erase(rit);
229 }
230
231 for (std::map<string, BatteryInterface *>::iterator biit = m_battery_interfaces.begin();
232 biit != m_battery_interfaces.end();
233 ++biit) {
234 // update data in interface
235 BatteryInterface *bi = biit->second;
236
237 try {
238 bi->read();
239 } catch (Exception &e) {
240 e.append("read() failed");
241 e.print_trace();
242 continue;
243 }
244
245 if (!bi->has_writer())
246 // only consider interfaces which have a writer
247 {
248 continue;
249 }
250
251 Gtk::TreeModel::Row row;
252 row = *m_battery_list->append();
253 row[m_battery_record.fqdn] = Glib::ustring(biit->first);
254
255 char *fqdn = strdup((biit->first).c_str());
256 char *sh;
257 char delim = '.';
258 sh = strtok(fqdn, &delim);
259 int i = atoi(sh);
260
261 if (0 != i) {
262 row[m_battery_record.short_name] = Glib::ustring(biit->first);
263 } else {
264 row[m_battery_record.short_name] = Glib::ustring(sh);
265 }
266
267 row[m_battery_record.absolute_soc] = bi->absolute_soc() * 100.0;
268 row[m_battery_record.relative_soc] = bi->relative_soc() * 100.0;
269 row[m_battery_record.current] = bi->current() / 1000.0;
270 row[m_battery_record.voltage] = bi->voltage() / 1000.0;
271
272 string fqdn_str = string(fqdn);
273 if (row[m_battery_record.relative_soc] <= m_relative_soc_threshold) {
274 unsigned int cnt = m_below_threshold_counter[fqdn_str];
275 m_below_threshold_counter[fqdn_str] = ++cnt;
276 } else {
277 m_below_threshold_counter[fqdn_str] = 0;
278 }
279
280 free(fqdn);
281 }
282
283 Glib::ustring secondary = "The batteries on ";
284 bool below_threshold = false;
285
286 for (std::map<string, unsigned int>::iterator i = m_below_threshold_counter.begin();
287 i != m_below_threshold_counter.end();
288 ++i) {
289 if (i->second > 2) {
290 secondary += "<b>" + Glib::ustring((i->first).c_str()) + "</b>" + " ";
291 i->second = 0;
292
293 below_threshold = true;
294 }
295 }
296 secondary += "need to be replaced.";
297
298 if (below_threshold) {
299 m_dlg_warning->set_secondary_text(secondary, true);
300 m_dlg_warning->set_urgency_hint();
301 m_dlg_warning->run();
302 m_dlg_warning->hide();
303 }
304}
305
306void
307BatteryMonitorTreeView::on_data_changed(fawkes::Interface *interface)
308{
309 update();
310}
311
312void
313BatteryMonitorTreeView::on_writer_added(fawkes::Interface *interface)
314{
315 update();
316}
317
318void
319BatteryMonitorTreeView::on_writer_removed(fawkes::Interface *interface)
320{
321 update();
322}
Gtk::TreeModelColumn< float > relative_soc
The battery's relative state of charge.
Gtk::TreeModelColumn< float > absolute_soc
The battery's absolute state of charge.
Gtk::TreeModelColumn< Glib::ustring > short_name
A shorter hostname (w/o domain)
Gtk::TreeModelColumn< float > current
The battery's current.
Gtk::TreeModelColumn< Glib::ustring > fqdn
The FQDN.
Gtk::TreeModelColumn< float > voltage
The battery's voltage.
virtual ~BatteryMonitorTreeView()
Destructor.
std::map< std::string, fawkes::BlackBoard * > m_remote_bbs
Map with remote blackboards: hostname -> remote blackboard.
void rem_host(const char *host)
Remove given host.
std::map< std::string, fawkes::BatteryInterface * > m_battery_interfaces
Map containing the battery interfaces: hostname -> battery interface.
BatteryMonitorTreeView(BaseObjectType *cobject, const Glib::RefPtr< Gtk::Builder > &builder)
Constructor.
BatteryRecord m_battery_record
Column record object to acces the columns of the storage object.
std::map< std::string, fawkes::InterfaceDispatcher * > m_interface_dispatcher
Interface dispatcher for the battery interfaces.
void add_host(const char *host)
Add given host.
Glib::RefPtr< Gtk::ListStore > m_battery_list
Storage object.
BatteryInterface Fawkes BlackBoard Interface.
uint32_t voltage() const
Get voltage value.
float absolute_soc() const
Get absolute_soc value.
float relative_soc() const
Get relative_soc value.
uint32_t current() const
Get current value.
The BlackBoard abstract class.
Definition: blackboard.h:46
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:212
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:185
virtual void close(Interface *interface)=0
Close interface.
Base class for exceptions in Fawkes.
Definition: exception.h:36
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Interface listener with dispatcher.
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:479
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:848
Remote BlackBoard.
Definition: remote.h:50
Fawkes library namespace.