GuiHealthClientWidgetController.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * \package RobotAPI::gui-plugins::GuiHealthClientWidgetController
17 * \author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
18 * \date 2018
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <RobotAPI/gui-plugins/GuiHealthClient/ui_GuiHealthClientWidget.h>
26
27#include <iomanip>
28#include <string>
29
30#include <QLabel>
31#include <QPushButton>
32#include <qcolor.h>
33#include <qnamespace.h>
34#include <qrgb.h>
35#include <qtablewidget.h>
36
37#include <SimoxUtility/algorithm/get_map_keys_values.h>
38
42
43namespace armarx
44{
45 std::string
46 serializeList(const std::vector<std::string>& l)
47 {
48 std::string s;
49 for (std::size_t i = 0; i < l.size(); i++)
50 {
51 const auto& tag = l.at(i);
52 s += tag;
53
54 if (i != l.size() - 1)
55 {
56 s += ", ";
57 }
58 }
59
60 return s;
61 }
62
64 {
65 widget = std::make_unique<Ui::GuiHealthClientWidget>();
66 widget->setupUi(getWidget());
67
68 connect(this,
70 this,
72 Qt::QueuedConnection);
73 connect(this,
75 this,
77 Qt::QueuedConnection);
78
79 connect(widget->pushButtonUnrequireAll, SIGNAL(clicked()), this, SLOT(unrequireAll()));
80
81 updateSummaryTimer = new QTimer(this);
82 updateSummaryTimer->setInterval(100);
83 connect(updateSummaryTimer, SIGNAL(timeout()), this, SLOT(updateSummaryTimerClb()));
84 }
85
89
90 void
92 {
93 }
94
95 void
97 {
98 }
99
100 void
102 {
103 //ARMARX_IMPORTANT << "onInitComponent";
104 usingProxy("RobotHealth");
105 offeringTopic("RobotHealthTopic");
106 }
107
108 void
110 {
111 armarx::core::time::dto::DateTime now;
113 robotHealthTopicPrx->heartbeat(getName(), now);
114 }
115
116 std::string
117 to_string_rounded(float value, int decimals = 100)
118 {
119 std::stringstream ss;
120 ss << std::fixed << std::setprecision(3) << value;
121 return ss.str();
122 }
123
124 QTableWidgetItem*
125 make_item(const std::string& text, Qt::AlignmentFlag horAlignment = Qt::AlignLeft)
126 {
127 auto* item = new QTableWidgetItem(QString::fromStdString(text));
128 item->setTextAlignment(horAlignment | Qt::AlignVCenter);
129 return item;
130 }
131
132 void
134 {
135 //ARMARX_IMPORTANT << "updateSummaryTimerClb";
136 if (robotHealthComponentPrx)
137 {
138 //ARMARX_IMPORTANT << "has robotHealthComponentPrx";
139 try
140 {
141 auto summary = robotHealthComponentPrx->getSummary();
142
143 const std::size_t nCols = 10;
144
145 auto& tableWidget = widget->tableHealthState;
146 tableWidget->setRowCount(summary.entries.size());
147 tableWidget->setColumnCount(nCols);
148
149 const auto summaryVals = simox::alg::get_values(summary.entries);
150
151 tableWidget->setHorizontalHeaderLabels({"identifier",
152 "required",
153 "keeps frequency",
154 "tags",
155 "time since\nlast arrival [ms]",
156 "time to\nreference [ms]",
157 "time sync \n+ Ice [ms]",
158 "warning\nthreshold [ms]",
159 "error\nthreshold [ms]",
160 "hostname"});
161
162 tableWidget->setColumnWidth(0, 250);
163 tableWidget->setColumnWidth(1, 80);
164 tableWidget->setColumnWidth(2, 120);
165 tableWidget->setColumnWidth(3, 180);
166 tableWidget->setColumnWidth(4, 120);
167 tableWidget->setColumnWidth(5, 120);
168 tableWidget->setColumnWidth(6, 120);
169 tableWidget->setColumnWidth(7, 120);
170
171 for (std::size_t i = 0; i < summary.entries.size(); i++)
172 {
173 const auto& entry = summaryVals.at(i);
174
175 std::string stateRepr;
176 QColor stateColor;
177 switch (entry.state)
178 {
179 case HealthOK:
180 stateRepr = "yes";
181 stateColor.setRgb(0, 255, 0); // green
182 break;
183 case HealthWarning:
184 stateRepr = "yes";
185 stateColor.setRgb(255, 165, 0); // orange
186 break;
187 case HealthError:
188 stateRepr = "no";
189 stateColor.setRgb(255, 0, 0); // red
190 break;
191 }
192
193 const std::string hostname = entry.lastReferenceTimestamp.hostname;
194
195 const std::string timeSinceLastArrivalRepr =
196 to_string_rounded(entry.timeSinceLastArrival.microSeconds / 1000.0);
197 const std::string timeToLastReferenceRepr =
198 to_string_rounded(entry.timeSinceLastUpdateReference.microSeconds / 1000.0);
199 const std::string tagsRepr = serializeList(entry.tags);
200
201 const float syncErrorMilliSeconds =
202 std::abs(entry.timeSinceLastArrival.microSeconds -
203 entry.timeSinceLastUpdateReference.microSeconds) /
204 1000.0;
205
206 tableWidget->setItem(
207 i, 0, new QTableWidgetItem(QString::fromStdString(entry.identifier)));
208 tableWidget->setItem(
209 i, 1, make_item(entry.required ? "yes" : "no", Qt::AlignHCenter));
210
211 {
212 auto* item = make_item(stateRepr, Qt::AlignHCenter);
213 item->setBackgroundColor(stateColor);
214 tableWidget->setItem(i, 2, item);
215 }
216
217 tableWidget->setItem(
218 i, 3, new QTableWidgetItem(QString::fromStdString(tagsRepr)));
219 tableWidget->setItem(i, 4, make_item(timeSinceLastArrivalRepr, Qt::AlignRight));
220 tableWidget->setItem(i, 5, make_item(timeToLastReferenceRepr, Qt::AlignRight));
221
222 {
223 auto* item =
224 make_item(to_string_rounded(syncErrorMilliSeconds), Qt::AlignRight);
225
226 QColor timeSyncColor;
227 if (syncErrorMilliSeconds > 20.)
228 {
229 timeSyncColor.setRgb(255, 0, 0);
230 }
231 else
232 {
233 timeSyncColor.setRgb(0, 255, 0);
234 }
235 item->setBackgroundColor(timeSyncColor);
236
237 tableWidget->setItem(i, 6, item);
238 }
239
240 tableWidget->setItem(
241 i,
242 7,
243 make_item(
244 to_string_rounded(entry.maximumCycleTimeWarning.microSeconds / 1000.),
245 Qt::AlignRight));
246 tableWidget->setItem(
247 i,
248 8,
249 make_item(
250 to_string_rounded(entry.maximumCycleTimeError.microSeconds / 1000.),
251 Qt::AlignRight));
252 tableWidget->setItem(
253 i, 9, new QTableWidgetItem(QString::fromStdString(hostname)));
254 }
255
256 std::string tagsText = "Active tags: [";
257 {
258 std::sort(summary.activeTags.begin(), summary.activeTags.end());
259
260 tagsText += serializeList(summary.activeTags);
261
262 tagsText += "]";
263 }
264
265 widget->labelTags->setText(QString::fromStdString(tagsText));
266 }
267 catch (...)
268 {
269 }
270 }
271 }
272
273 void
275 {
276 ARMARX_INFO << "UnrequireAll.";
277 if (robotHealthComponentPrx)
278 {
279 try
280 {
281 robotHealthComponentPrx->resetRequiredTags();
282 }
283 catch (...)
284 {
285 }
286 }
287 }
288
289 void
291 {
292 //ARMARX_IMPORTANT << "onConnectComponent";
293 robotHealthTopicPrx = getTopic<RobotHealthInterfacePrx>("RobotHealthTopic");
294 robotHealthComponentPrx = getProxy<RobotHealthComponentInterfacePrx>("RobotHealth");
296 }
297
298 void
300 {
301 //healthTimer->start();
302 //ARMARX_IMPORTANT <<ame "updateSummaryTimer->start";
303 updateSummaryTimer->start();
304 }
305
306 void
311
312 void
314 {
315 updateSummaryTimer->stop();
316 }
317} // namespace armarx
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
virtual ~GuiHealthClientWidgetController()
Controller destructor.
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
static DateTime Now()
Definition DateTime.cpp:51
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:179
void toIce(dto::ClockType::ClockTypeEnum &dto, const ClockType &bo)
This file offers overloads of toIce() and fromIce() functions for STL container types.
QTableWidgetItem * make_item(const std::string &text, Qt::AlignmentFlag horAlignment=Qt::AlignLeft)
std::string serializeList(const std::vector< std::string > &l)
std::string to_string_rounded(float value, int decimals=100)