modbus_tcp.cpp
Go to the documentation of this file.
2 
3 namespace industrial_modbus_tcp
4 {
5 
6 ModbusTCP::ModbusTCP(QWidget *parent) :
7  rviz::Panel(parent)
8 {
9  connect(this, &ModbusTCP::enable, this, &ModbusTCP::setEnabled);
10  qRegisterMetaType<QMessageBox::Icon>();
12 
13  setObjectName("ModbusTCP");
14  setName(objectName());
15 
16  QVBoxLayout *layout(new QVBoxLayout);
17  QWidget *scroll_widget = new QWidget;
18  scroll_widget->setLayout(layout);
19  QScrollArea *scroll_area = new QScrollArea;
20  scroll_area->setWidget(scroll_widget);
21  scroll_area->setWidgetResizable(true);
22  scroll_area->setFrameShape(QFrame::NoFrame);
23  QVBoxLayout *main_layout = new QVBoxLayout(this);
24  main_layout->addWidget(scroll_area);
25 
26  stack_ = new QStackedWidget;
27  QWidget *tab_base_topic(new QWidget);
28  QVBoxLayout *tab_base_topic_layout(new QVBoxLayout(tab_base_topic));
29  QWidget *tab_configure(new QWidget);
30  QVBoxLayout *tab_configure_layout(new QVBoxLayout(tab_configure));
31  stack_->addWidget(tab_base_topic);
32  stack_->addWidget(tab_configure);
33  layout->addWidget(stack_);
34 
35  base_topic_line_edit_ = new QLineEdit;
36  base_topic_line_edit_->setText("industrial_modbus_tcp");
37  QHBoxLayout *base_topic_layout(new QHBoxLayout);
38  base_topic_layout->addWidget(new QLabel("Base topic: "));
39  base_topic_layout->addWidget(base_topic_line_edit_);
40 
41  change_base_topic_ = new QPushButton("Ok");
42  tab_base_topic_layout->addLayout(base_topic_layout);
43  tab_base_topic_layout->addStretch(1);
44  tab_base_topic_layout->addWidget(change_base_topic_);
45 
46  connect(this, &ModbusTCP::setStackIndex, this, [=](const int index)
47  {
48  stack_->setCurrentIndex(index);
49  });
50 
51  connect(change_base_topic_, &QPushButton::clicked, this, [ = ]()
52  {
53  base_topic_ = base_topic_line_edit_->text().toStdString();
54  configure_modbus_ = nh_.serviceClient<industrial_modbus_tcp::Configure>(base_topic_ + "/configure");
56  QtConcurrent::run(this, &ModbusTCP::connectToService);
57  });
58 
59  QPushButton *configure = new QPushButton("Configure");
60  connect(configure, &QPushButton::clicked, this, &ModbusTCP::configureButtonHandler);
61 
62  errors_log_ = new QTableWidget(0, 2);
63  {
64  QStringList columns;
65  columns.append("Time");
66  columns.append("Error");
67  errors_log_->setHorizontalHeaderLabels(columns);
68  errors_log_->setColumnWidth(0, 130);
69  errors_log_->setColumnWidth(1, 250);
70  }
71  connect(this, &ModbusTCP::newError, this, &ModbusTCP::newErrorHandler);
72 
73  tab_configure_layout->addWidget(configure);
74  tab_configure_layout->addStretch(1);
75  tab_configure_layout->addWidget(new QLabel("Errors:"));
76  tab_configure_layout->addWidget(errors_log_);
77 }
78 
80 {
81 }
82 
83 void ModbusTCP::errorsCallback(const std_msgs::String::ConstPtr &msg)
84 {
85  Q_EMIT newError(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"), QString::fromStdString(msg->data));
86 }
87 
88 void ModbusTCP::newErrorHandler(const QString time, const QString msg)
89 {
90  if (errors_log_->rowCount() >= 50)
91  errors_log_->removeRow(0);
92 
93  errors_log_->setRowCount(errors_log_->rowCount() + 1);
94  QLabel *time_label(new QLabel(time));
95  QLabel *msg_label(new QLabel(msg));
96  errors_log_->setCellWidget(errors_log_->rowCount() - 1, 0, time_label);
97  errors_log_->setCellWidget(errors_log_->rowCount() - 1, 1, msg_label);
98  errors_log_->setCurrentCell(errors_log_->rowCount() - 1, 0);
99 }
100 
102 {
104 
105  if (!dialog->exec())
106  return;
107 
108  try
109  {
111  }
112  catch (std::runtime_error &e)
113  {
114  Q_EMIT enable(true);
115  Q_EMIT displayMessageBox("Error in handlers",
116  "The new configuration will not take effect because one of the handler contains an error:",
117  e.what(),
118  QMessageBox::Icon::Warning);
119  return;
120  }
121 
122  Q_EMIT configChanged();
123 
124  if (configure_modbus_srv_.request.handlers.empty())
125  return;
126 
127  Q_EMIT enable(false);
128  QtConcurrent::run(this, &ModbusTCP::configure);
129 }
130 
132 {
133  if (configure_modbus_srv_.request.handlers.empty())
134  return;
135 
137  {
138  Q_EMIT enable(true);
139  Q_EMIT displayMessageBox("Failed to call service",
140  "Could not call service to configure Modbus TCP",
141  "",
142  QMessageBox::Icon::Critical);
143  return;
144  }
145 
146  if (!configure_modbus_srv_.response.error.empty())
147  {
148  Q_EMIT enable(true);
149  Q_EMIT displayMessageBox("Failed to call service",
150  "Service call to configure Modbus TCP failed:",
151  QString::fromStdString(configure_modbus_srv_.response.error),
152  QMessageBox::Icon::Warning);
153  return;
154  }
155 
156  Q_EMIT enable(true);
157 }
158 
159 void ModbusTCP::load(const rviz::Config &config)
160 {
161  rviz::Panel::load(config);
162 
163  bool tmp_bool;
164  int tmp_int;
165  QString tmp_str;
166 
167  unsigned i(0);
168  while (1)
169  {
170  industrial_modbus_tcp::ModbusHandler handler;
171 
172  tmp_str.clear();
173  if (!config.mapGetString("handler_" + QString::number(i) + "_ip_address", &tmp_str))
174  break;
175  if (tmp_str.isEmpty())
176  break;
177  handler.ip_address = tmp_str.toStdString();
178 
179  tmp_str.clear();
180  if (!config.mapGetString("handler_" + QString::number(i) + "_name", &tmp_str))
181  break;
182  if (tmp_str.isEmpty())
183  break;
184  handler.name = tmp_str.toStdString();
185 
186  if (config.mapGetInt("handler_" + QString::number(i) + "_port", &tmp_int))
187  handler.port = tmp_int;
188 
189  if (config.mapGetInt("handler_" + QString::number(i) + "_recovery_mode", &tmp_int))
190  handler.modbus_error_recovery_mode = tmp_int;
191 
192  // Load data
193  unsigned j(0);
194 
195  // Bool
196  j = 0;
197  while (1)
198  {
199  industrial_modbus_tcp::Bool d;
200  if (!parseDataReg(config, i, j, "bool", d.reg))
201  break;
202 
203  QString token("handler_" + QString::number(i) + "_bool_" + QString::number(j) + "_mask");
204  if (!config.mapGetInt(token, &tmp_int))
205  break;
206  d.mask = tmp_int;
207 
208  handler.d_bool.emplace_back(d);
209  ++j;
210  }
211 
212  // Int8 and UInt8
213  j = 0;
214  while (1)
215  {
216  industrial_modbus_tcp::Int8 d;
217  if (!parseDataReg(config, i, j, "int8", d.reg))
218  break;
219 
220  QString token("handler_" + QString::number(i) + "_int8_" + QString::number(j) + "_bit_shift");
221  if (!config.mapGetInt(token, &tmp_int))
222  break;
223  d.bit_shift = tmp_int;
224 
225  handler.d_int8.emplace_back(d);
226  ++j;
227  }
228  j = 0;
229  while (1)
230  {
231  industrial_modbus_tcp::UInt8 d;
232  if (!parseDataReg(config, i, j, "uint8", d.reg))
233  break;
234 
235  QString token("handler_" + QString::number(i) + "_uint8_" + QString::number(j) + "_bit_shift");
236  if (!config.mapGetInt(token, &tmp_int))
237  break;
238  d.bit_shift = tmp_int;
239 
240  handler.d_uint8.emplace_back(d);
241  ++j;
242  }
243 
244  // Int16 and UInt16
245  j = 0;
246  while (1)
247  {
248  industrial_modbus_tcp::Int16 d;
249  if (!parseDataReg(config, i, j, "int16", d.reg))
250  break;
251 
252  handler.d_int16.emplace_back(d);
253  ++j;
254  }
255  j = 0;
256  while (1)
257  {
258  industrial_modbus_tcp::UInt16 d;
259  if (!parseDataReg(config, i, j, "uint16", d.reg))
260  break;
261 
262  handler.d_uint16.emplace_back(d);
263  ++j;
264  }
265 
266  // Int32 and UInt32
267  j = 0;
268  while (1)
269  {
270  industrial_modbus_tcp::Int32 d;
271  if (!parseDataReg(config, i, j, "int32", d.reg))
272  break;
273 
274  QString token("handler_" + QString::number(i) + "_int32_" + QString::number(j) + "_big_endian");
275  if (!config.mapGetBool(token, &tmp_bool))
276  break;
277  d.big_endian = tmp_bool;
278 
279  handler.d_int32.emplace_back(d);
280  ++j;
281  }
282  j = 0;
283  while (1)
284  {
285  industrial_modbus_tcp::UInt32 d;
286  if (!parseDataReg(config, i, j, "uint32", d.reg))
287  break;
288 
289  QString token("handler_" + QString::number(i) + "_uint32_" + QString::number(j) + "_big_endian");
290  if (!config.mapGetBool(token, &tmp_bool))
291  break;
292  d.big_endian = tmp_bool;
293 
294  handler.d_uint32.emplace_back(d);
295  ++j;
296  }
297 
298  // Int64 and UInt64
299  j = 0;
300  while (1)
301  {
302  industrial_modbus_tcp::Int64 d;
303  if (!parseDataReg(config, i, j, "int64", d.reg))
304  break;
305 
306  QString token("handler_" + QString::number(i) + "_int64_" + QString::number(j) + "_big_endian");
307  if (!config.mapGetBool(token, &tmp_bool))
308  break;
309  d.big_endian = tmp_bool;
310 
311  handler.d_int64.emplace_back(d);
312  ++j;
313  }
314  j = 0;
315  while (1)
316  {
317  industrial_modbus_tcp::UInt64 d;
318  if (!parseDataReg(config, i, j, "uint64", d.reg))
319  break;
320 
321  QString token("handler_" + QString::number(i) + "_uint64_" + QString::number(j) + "_big_endian");
322  if (!config.mapGetBool(token, &tmp_bool))
323  break;
324  d.big_endian = tmp_bool;
325 
326  handler.d_uint64.emplace_back(d);
327  ++j;
328  }
329 
330  // Float32 and Float64
331  j = 0;
332  while (1)
333  {
334  industrial_modbus_tcp::Float32 d;
335  if (!parseDataReg(config, i, j, "float32", d.reg))
336  break;
337 
338  QString token("handler_" + QString::number(i) + "_float32_" + QString::number(j) + "_big_endian");
339  if (!config.mapGetBool(token, &tmp_bool))
340  break;
341  d.big_endian = tmp_bool;
342 
343  handler.d_float32.emplace_back(d);
344  ++j;
345  }
346  j = 0;
347  while (1)
348  {
349  industrial_modbus_tcp::Float64 d;
350  if (!parseDataReg(config, i, j, "float64", d.reg))
351  break;
352 
353  QString token("handler_" + QString::number(i) + "_float64_" + QString::number(j) + "_big_endian");
354  if (!config.mapGetBool(token, &tmp_bool))
355  break;
356  d.big_endian = tmp_bool;
357 
358  handler.d_float64.emplace_back(d);
359  ++j;
360  }
361 
362  configure_modbus_srv_.request.handlers.push_back(handler);
363  ++i;
364  }
365 
366  if (config.mapGetString("base_topic", &tmp_str))
367  {
368  base_topic_line_edit_->setText(tmp_str);
369  Q_EMIT change_base_topic_->clicked();
370  }
371 }
372 
374  const unsigned i,
375  const unsigned j,
376  const std::string name,
377  industrial_modbus_tcp::Register &r)
378 {
379  int tmp_int;
380  QString tmp_str;
381 
382  tmp_str.clear();
383  QString token("handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_address");
384  if (!config.mapGetInt(token, &tmp_int))
385  return false;
386  r.address = tmp_int;
387 
388  token = "handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_topic_name";
389  if (!config.mapGetString(token, &tmp_str))
390  return false;
391  r.topic_name = tmp_str.toStdString();
392 
393  token = "handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_poll_rate_usec";
394  if (!config.mapGetInt(token, &tmp_int))
395  return false;
396  r.poll_rate_usec = tmp_int;
397 
398  return true;
399 }
400 
402  const unsigned i,
403  const unsigned j,
404  const std::string name,
405  const industrial_modbus_tcp::Register &r) const
406 {
407  config.mapSetValue("handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_address",
408  r.address);
409  config.mapSetValue("handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_topic_name",
410  QString::fromStdString(r.topic_name));
411  config.mapSetValue("handler_" + QString::number(i) + "_" + QString::fromStdString(name) + "_" + QString::number(j) + "_poll_rate_usec",
412  r.poll_rate_usec);
413 }
414 
415 void ModbusTCP::save(rviz::Config config) const
416 {
417  rviz::Panel::save(config);
418  if (!base_topic_.empty())
419  config.mapSetValue("base_topic", QString::fromStdString(base_topic_));
420 
421  for (std::size_t i(0); i < configure_modbus_srv_.request.handlers.size(); ++i)
422  {
423  config.mapSetValue("handler_" + QString::number(i) +
424  "_ip_address",
425  QString::fromStdString(configure_modbus_srv_.request.handlers[i].ip_address));
426  config.mapSetValue("handler_" + QString::number(i) +
427  "_name",
428  QString::fromStdString(configure_modbus_srv_.request.handlers[i].name));
429  config.mapSetValue("handler_" + QString::number(i) +
430  "_port",
431  configure_modbus_srv_.request.handlers[i].port);
432  config.mapSetValue("handler_" + QString::number(i) +
433  "_recovery_mode",
434  configure_modbus_srv_.request.handlers[i].modbus_error_recovery_mode);
435 
436  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_bool.size(); ++j)
437  {
438  saveDataReg(config, i, j, "bool", configure_modbus_srv_.request.handlers.at(i).d_bool.at(j).reg);
439  config.mapSetValue("handler_" + QString::number(i) + "_bool_" + QString::number(j) + "_mask",
440  configure_modbus_srv_.request.handlers.at(i).d_bool.at(j).mask);
441  }
442 
443  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_int8.size(); ++j)
444  {
445  saveDataReg(config, i, j, "int8", configure_modbus_srv_.request.handlers.at(i).d_int8.at(j).reg);
446  config.mapSetValue("handler_" + QString::number(i) + "_int8_" + QString::number(j) + "_bit_shift",
447  configure_modbus_srv_.request.handlers.at(i).d_int8.at(j).bit_shift);
448  }
449 
450  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_uint8.size(); ++j)
451  {
452  saveDataReg(config, i, j, "uint8", configure_modbus_srv_.request.handlers.at(i).d_uint8.at(j).reg);
453  config.mapSetValue("handler_" + QString::number(i) + "_uint8_" + QString::number(j) + "_bit_shift",
454  configure_modbus_srv_.request.handlers.at(i).d_uint8.at(j).bit_shift);
455  }
456 
457  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_int16.size(); ++j)
458  {
459  saveDataReg(config, i, j, "int16", configure_modbus_srv_.request.handlers.at(i).d_int16.at(j).reg);
460  }
461 
462  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_uint16.size(); ++j)
463  {
464  saveDataReg(config, i, j, "uint16", configure_modbus_srv_.request.handlers.at(i).d_uint16.at(j).reg);
465  }
466 
467  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_int32.size(); ++j)
468  {
469  saveDataReg(config, i, j, "int32", configure_modbus_srv_.request.handlers.at(i).d_int32.at(j).reg);
470  config.mapSetValue("handler_" + QString::number(i) + "_int32_" + QString::number(j) + "_big_endian",
471  configure_modbus_srv_.request.handlers.at(i).d_int32.at(j).big_endian);
472  }
473 
474  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_uint32.size(); ++j)
475  {
476  saveDataReg(config, i, j, "uint32", configure_modbus_srv_.request.handlers.at(i).d_uint32.at(j).reg);
477  config.mapSetValue("handler_" + QString::number(i) + "_uint32_" + QString::number(j) + "_big_endian",
478  configure_modbus_srv_.request.handlers.at(i).d_uint32.at(j).big_endian);
479  }
480 
481  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_float32.size(); ++j)
482  {
483  saveDataReg(config, i, j, "float32", configure_modbus_srv_.request.handlers.at(i).d_float32.at(j).reg);
484  config.mapSetValue("handler_" + QString::number(i) + "_float32_" + QString::number(j) + "_big_endian",
485  configure_modbus_srv_.request.handlers.at(i).d_float32.at(j).big_endian);
486  }
487 
488  for (std::size_t j(0); j < configure_modbus_srv_.request.handlers.at(i).d_float64.size(); ++j)
489  {
490  saveDataReg(config, i, j, "float64", configure_modbus_srv_.request.handlers.at(i).d_float64.at(j).reg);
491  config.mapSetValue("handler_" + QString::number(i) + "_float64_" + QString::number(j) + "_big_endian",
492  configure_modbus_srv_.request.handlers.at(i).d_float64.at(j).big_endian);
493  }
494  }
495 }
496 
498 {
499  Q_EMIT enable(false);
501  {
502  Q_EMIT setStackIndex(0);
503  Q_EMIT enable(true);
504  Q_EMIT displayMessageBox("Failed to connect to service",
505  QString::fromStdString(configure_modbus_.getService()),
506  "",
507  QMessageBox::Icon::Warning);
508  return;
509  }
510 
511  Q_EMIT setStackIndex(1);
512  Q_EMIT enable(true);
513  Q_EMIT configChanged();
514  configure(); // Send configuration (if any)
515 }
516 
518  const QString title,
519  const QString text,
520  const QString info,
521  const QMessageBox::Icon icon)
522 {
523  const bool old_state(isEnabled());
524  setEnabled(false);
525  QMessageBox msg_box;
526  msg_box.setWindowTitle(title);
527  msg_box.setText(text);
528  msg_box.setInformativeText(info);
529  msg_box.setIcon(icon);
530  msg_box.setStandardButtons(QMessageBox::Ok);
531  msg_box.exec();
532  setEnabled(old_state);
533 }
534 
535 }
536 
d
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
virtual void load(const rviz::Config &config)
Definition: modbus_tcp.cpp:159
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void getConfigureRequest(industrial_modbus_tcp::ConfigureRequest &req)
bool call(MReq &req, MRes &res)
ModbusTCP(QWidget *parent=NULL)
Definition: modbus_tcp.cpp:6
virtual void save(Config config) const
bool mapGetString(const QString &key, QString *value_out) const
void configChanged()
void displayMessageBox(const QString, const QString, const QString, const QMessageBox::Icon)
industrial_modbus_tcp::Configure configure_modbus_srv_
Definition: modbus_tcp.hpp:73
void mapSetValue(const QString &key, QVariant value)
virtual void setName(const QString &name)
virtual void save(rviz::Config config) const
Definition: modbus_tcp.cpp:415
bool parseDataReg(const rviz::Config &config, const unsigned i, const unsigned j, const std::string name, industrial_modbus_tcp::Register &r)
Definition: modbus_tcp.cpp:373
void newError(const QString, const QString)
bool waitForExistence(ros::Duration timeout=ros::Duration(-1))
virtual void saveDataReg(rviz::Config &config, const unsigned i, const unsigned j, const std::string name, const industrial_modbus_tcp::Register &r) const
Definition: modbus_tcp.cpp:401
void newErrorHandler(const QString, const QString)
Definition: modbus_tcp.cpp:88
bool mapGetBool(const QString &key, bool *value_out) const
void displayMessageBoxHandler(const QString title, const QString text, const QString info, const QMessageBox::Icon icon)
Definition: modbus_tcp.cpp:517
std::string getService()
virtual void load(const Config &config)
ros::ServiceClient configure_modbus_
Definition: modbus_tcp.hpp:72
bool mapGetInt(const QString &key, int *value_out) const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void errorsCallback(const std_msgs::String::ConstPtr &msg)
Definition: modbus_tcp.cpp:83


industrial_modbus_tcp
Author(s): Victor Lamoine - Institut Maupertuis
autogenerated on Mon Feb 28 2022 22:33:12