modbus_tcp_handler.cpp
Go to the documentation of this file.
2 
3 namespace industrial_modbus_tcp
4 {
5 
6 ModbusTCPHandler::ModbusTCPHandler(industrial_modbus_tcp::ModbusHandler h)
7 {
8  layout_ = new QVBoxLayout();
9  setLayout(layout_);
10 
11  name_ = new QLineEdit(QString::fromStdString(h.name));
12  connect(name_, &QLineEdit::textChanged, this, &ModbusTCPHandler::nameChanged);
13  ip_address_ = new QLineEdit(QString::fromStdString(h.ip_address));
14  ip_address_->setInputMask("000.000.000.000;_");
15  port_ = new QSpinBox;
16  port_->setRange(0, 1000);
17  port_->setValue(h.port);
18  recovery_ = new QComboBox;
19  recovery_->addItem("None");
20  recovery_->addItem("Link");
21  recovery_->addItem("Protocol");
22  recovery_->addItem("Link and protocol");
23  recovery_->setCurrentIndex(h.modbus_error_recovery_mode);
24 
25  tabs_ = new QTabWidget;
26  for (std::size_t i(0); i < TAB_INDEX::SIZE; ++i)
27  tables_.emplace_back(new QTableWidget);
28 
29  {
30  QStringList labels;
31  labels.push_back("Topic name");
32  labels.push_back("Register address");
33  labels.push_back("Frequency (Hz)");
34  labels.push_back("Mask");
35  tables_.at(BOOL)->setColumnCount(labels.size());
36  tables_.at(BOOL)->setHorizontalHeaderLabels(labels);
37  }
38  {
39  QStringList labels;
40  labels.push_back("Topic name");
41  labels.push_back("Register address");
42  labels.push_back("Frequency (Hz)");
43  labels.push_back("Bit shift");
44  tables_.at(INT8)->setColumnCount(labels.size());
45  tables_.at(INT8)->setHorizontalHeaderLabels(labels);
46  tables_.at(UINT8)->setColumnCount(labels.size());
47  tables_.at(UINT8)->setHorizontalHeaderLabels(labels);
48  }
49  {
50  QStringList labels;
51  labels.push_back("Topic name");
52  labels.push_back("Register address");
53  labels.push_back("Frequency (Hz)");
54  tables_.at(INT16)->setColumnCount(labels.size());
55  tables_.at(INT16)->setHorizontalHeaderLabels(labels);
56  tables_.at(UINT16)->setColumnCount(labels.size());
57  tables_.at(UINT16)->setHorizontalHeaderLabels(labels);
58  }
59  {
60  QStringList labels;
61  labels.push_back("Topic name");
62  labels.push_back("Register address");
63  labels.push_back("Frequency (Hz)");
64  labels.push_back("Endianness");
65  tables_.at(INT32)->setColumnCount(labels.size());
66  tables_.at(INT32)->setHorizontalHeaderLabels(labels);
67  tables_.at(UINT32)->setColumnCount(labels.size());
68  tables_.at(UINT32)->setHorizontalHeaderLabels(labels);
69  tables_.at(INT64)->setColumnCount(labels.size());
70  tables_.at(INT64)->setHorizontalHeaderLabels(labels);
71  tables_.at(UINT64)->setColumnCount(labels.size());
72  tables_.at(UINT64)->setHorizontalHeaderLabels(labels);
73  tables_.at(FLOAT32)->setColumnCount(labels.size());
74  tables_.at(FLOAT32)->setHorizontalHeaderLabels(labels);
75  tables_.at(FLOAT64)->setColumnCount(labels.size());
76  tables_.at(FLOAT64)->setHorizontalHeaderLabels(labels);
77  }
78 
79  tabs_->addTab(tables_.at(BOOL), "bool");
80  tabs_->addTab(tables_.at(INT8), "int8");
81  tabs_->addTab(tables_.at(UINT8), "uint8");
82  tabs_->addTab(tables_.at(INT16), "int16");
83  tabs_->addTab(tables_.at(UINT16), "uint16");
84  tabs_->addTab(tables_.at(INT32), "int32");
85  tabs_->addTab(tables_.at(UINT32), "uint32");
86  tabs_->addTab(tables_.at(INT64), "int64");
87  tabs_->addTab(tables_.at(UINT64), "uint64");
88  tabs_->addTab(tables_.at(FLOAT32), "float32");
89  tabs_->addTab(tables_.at(FLOAT64), "float64");
90 
91  for (auto table : tables_)
92  {
93  table->setColumnWidth(0, 300);
94  table->setColumnWidth(1, 120);
95  table->setColumnWidth(2, 120);
96  }
97 
98  add_data_ = new QPushButton("+");
99  remove_data_ = new QPushButton("-");
100 
101  QHBoxLayout *name_layout = new QHBoxLayout;
102  name_layout->addWidget(new QLabel("Name"));
103  name_layout->addWidget(name_);
104 
105  QHBoxLayout *ip_layout = new QHBoxLayout;
106  ip_layout->addWidget(new QLabel("IP address"));
107  ip_layout->addWidget(ip_address_);
108 
109  QHBoxLayout *port_layout = new QHBoxLayout;
110  port_layout->addWidget(new QLabel("Port"));
111  port_layout->addWidget(port_);
112 
113  QHBoxLayout *recovery_layout = new QHBoxLayout;
114  recovery_layout->addWidget(new QLabel("Recovery"));
115  recovery_layout->addWidget(recovery_);
116 
117  QHBoxLayout *registers_op_layout = new QHBoxLayout;
118  registers_op_layout->addWidget(add_data_);
119  registers_op_layout->addWidget(remove_data_);
120  connect(add_data_, &QPushButton::clicked, this, &ModbusTCPHandler::addData);
121  connect(remove_data_, &QPushButton::clicked, this, &ModbusTCPHandler::removeData);
122 
123  layout_->addLayout(name_layout);
124  layout_->addLayout(ip_layout);
125  layout_->addLayout(port_layout);
126  layout_->addLayout(recovery_layout);
127  layout_->addWidget(tabs_);
128  layout_->addLayout(registers_op_layout);
129 
130  for (auto d : h.d_bool)
131  addBool(d);
132  for (auto d : h.d_int8)
133  addInt8(d);
134  for (auto d : h.d_uint8)
135  addUInt8(d);
136  for (auto d : h.d_int16)
137  addInt16(d);
138  for (auto d : h.d_uint16)
139  addUInt16(d);
140  for (auto d : h.d_int32)
141  addInt32(d);
142  for (auto d : h.d_uint32)
143  addUInt32(d);
144  for (auto d : h.d_int64)
145  addInt64(d);
146  for (auto d : h.d_uint64)
147  addUInt64(d);
148  for (auto d : h.d_float32)
149  addFloat32(d);
150  for (auto d : h.d_float64)
151  addFloat64(d);
152 }
153 
155 {
156 }
157 
159  const QTableWidget *table,
160  const unsigned row,
161  industrial_modbus_tcp::Register &r)
162 {
163  r.topic_name = static_cast<QLineEdit *>(table->cellWidget(row, 0))->text().toStdString();
164  r.address = static_cast<QSpinBox *>(table->cellWidget(row, 1))->value();
165  r.poll_rate_usec = (double) 1e6 / static_cast<QDoubleSpinBox *>(table->cellWidget(row, 2))->value();
166 }
167 
168 industrial_modbus_tcp::ModbusHandler ModbusTCPHandler::getHandler()
169 {
170  industrial_modbus_tcp::ModbusHandler handler;
171  handler.ip_address = ip_address_->text().toStdString();
172  handler.name = name_->text().toStdString();
173  handler.port = port_->value();
174  handler.modbus_error_recovery_mode = recovery_->currentIndex();
175 
176  if (handler.name.empty())
177  throw std::runtime_error("Handler name cannot be empty");
178 
179  {
180  QTableWidget *table(tables_.at(BOOL));
181  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
182  {
183  industrial_modbus_tcp::Bool d;
184  readRegisterTable(table, i, d.reg);
185  d.mask = static_cast<QSpinBox *>(table->cellWidget(i, 3))->value();
186  handler.d_bool.emplace_back(d);
187  }
188  }
189 
190  {
191  QTableWidget *table(tables_.at(INT8));
192  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
193  {
194  industrial_modbus_tcp::Int8 d;
195  readRegisterTable(table, i, d.reg);
196  d.bit_shift = static_cast<QSpinBox *>(table->cellWidget(i, 3))->value();
197  handler.d_int8.emplace_back(d);
198  }
199  }
200 
201  {
202  QTableWidget *table(tables_.at(UINT8));
203  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
204  {
205  industrial_modbus_tcp::UInt8 d;
206  readRegisterTable(table, i, d.reg);
207  d.bit_shift = static_cast<QSpinBox *>(table->cellWidget(i, 3))->value();
208  handler.d_uint8.emplace_back(d);
209  }
210  }
211 
212  {
213  QTableWidget *table(tables_.at(INT16));
214  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
215  {
216  industrial_modbus_tcp::Int16 d;
217  readRegisterTable(table, i, d.reg);
218  handler.d_int16.emplace_back(d);
219  }
220  }
221 
222  {
223  QTableWidget *table(tables_.at(UINT16));
224  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
225  {
226  industrial_modbus_tcp::UInt16 d;
227  readRegisterTable(table, i, d.reg);
228  handler.d_uint16.emplace_back(d);
229  }
230  }
231 
232  {
233  QTableWidget *table(tables_.at(INT32));
234  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
235  {
236  industrial_modbus_tcp::Int32 d;
237  readRegisterTable(table, i, d.reg);
238  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
239  handler.d_int32.emplace_back(d);
240  }
241  }
242 
243  {
244  QTableWidget *table(tables_.at(UINT32));
245  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
246  {
247  industrial_modbus_tcp::UInt32 d;
248  readRegisterTable(table, i, d.reg);
249  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
250  handler.d_uint32.emplace_back(d);
251  }
252  }
253 
254  {
255  QTableWidget *table(tables_.at(INT64));
256  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
257  {
258  industrial_modbus_tcp::Int64 d;
259  readRegisterTable(table, i, d.reg);
260  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
261  handler.d_int64.emplace_back(d);
262  }
263  }
264 
265  {
266  QTableWidget *table(tables_.at(UINT64));
267  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
268  {
269  industrial_modbus_tcp::UInt64 d;
270  readRegisterTable(table, i, d.reg);
271  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
272  handler.d_uint64.emplace_back(d);
273  }
274  }
275 
276  {
277  QTableWidget *table(tables_.at(FLOAT32));
278  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
279  {
280  industrial_modbus_tcp::Float32 d;
281  readRegisterTable(table, i, d.reg);
282  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
283  handler.d_float32.emplace_back(d);
284  }
285  }
286 
287  {
288  QTableWidget *table(tables_.at(FLOAT64));
289  for (std::size_t i(0); i < (std::size_t) table->rowCount(); ++i)
290  {
291  industrial_modbus_tcp::Float64 d;
292  readRegisterTable(table, i, d.reg);
293  d.big_endian = static_cast<QComboBox *>(table->cellWidget(i, 3))->currentIndex();
294  handler.d_float64.emplace_back(d);
295  }
296  }
297 
298  for (auto d : handler.d_bool)
299  if (d.reg.topic_name.empty())
300  throw std::runtime_error("Bool: Topic name cannot be empty!");
301 
302  for (auto d : handler.d_int8)
303  if (d.reg.topic_name.empty())
304  throw std::runtime_error("int8: Topic name cannot be empty!");
305 
306  for (auto d : handler.d_uint8)
307  if (d.reg.topic_name.empty())
308  throw std::runtime_error("uint8: Topic name cannot be empty!");
309 
310  for (auto d : handler.d_int16)
311  if (d.reg.topic_name.empty())
312  throw std::runtime_error("int16: Topic name cannot be empty!");
313 
314  for (auto d : handler.d_uint16)
315  if (d.reg.topic_name.empty())
316  throw std::runtime_error("uint16: Topic name cannot be empty!");
317 
318  for (auto d : handler.d_int32)
319  if (d.reg.topic_name.empty())
320  throw std::runtime_error("int32: Topic name cannot be empty!");
321 
322  for (auto d : handler.d_int64)
323  if (d.reg.topic_name.empty())
324  throw std::runtime_error("int64: Topic name cannot be empty!");
325 
326  for (auto d : handler.d_float32)
327  if (d.reg.topic_name.empty())
328  throw std::runtime_error("float32: Topic name cannot be empty!");
329 
330  for (auto d : handler.d_float64)
331  if (d.reg.topic_name.empty())
332  throw std::runtime_error("float64: Topic name cannot be empty!");
333 
334  return handler;
335 }
336 
338 {
339  return name_->text();
340 }
341 
342 void ModbusTCPHandler::addRegister(const industrial_modbus_tcp::Register &r,
343  QTableWidget *table)
344 {
345  QLineEdit *topic_name = new QLineEdit(QString::fromStdString(r.topic_name));
346  // Only letters, numbers and underscore
347  topic_name->setValidator(new QRegExpValidator(QRegExp("[A-Za-z0-9_/]+"), this));
348  table->setCellWidget(table->rowCount() - 1, 0, topic_name);
349 
350  QSpinBox *address = new QSpinBox;
351  address->setRange(0, 0x20000);
352  address->setValue(r.address);
353  table->setCellWidget(table->rowCount() - 1, 1, address);
354 
355  QDoubleSpinBox *frequency = new QDoubleSpinBox;
356  frequency->setRange(0.01, 1000);
357  frequency->setSingleStep(1);
358  frequency->setValue((double) 1e6 / r.poll_rate_usec);
359  table->setCellWidget(table->rowCount() - 1, 2, frequency);
360 }
361 
362 void ModbusTCPHandler::addBigEndian(const bool value, QTableWidget *table)
363 {
364  QComboBox *truefalse(new QComboBox);
365  truefalse->addItem("False");
366  truefalse->addItem("True");
367  truefalse->setCurrentIndex(value);
368  table->setCellWidget(table->rowCount() - 1, 3, truefalse);
369 }
370 
371 void ModbusTCPHandler::addBool(const industrial_modbus_tcp::Bool &d)
372 {
373  QTableWidget *table(tables_.at(BOOL));
374  table->insertRow(table->rowCount());
375  addRegister(d.reg, table);
376 
377  QSpinBox *mask(new QSpinBox);
378  mask->setRange(0, 65535);
379  mask->setValue(d.mask);
380  table->setCellWidget(table->rowCount() - 1, 3, mask);
381 }
382 
383 void ModbusTCPHandler::addInt8(const industrial_modbus_tcp::Int8 &d)
384 {
385  QTableWidget *table(tables_.at(INT8));
386  table->insertRow(table->rowCount());
387  addRegister(d.reg, table);
388 
389  QSpinBox *bit_shift(new QSpinBox);
390  bit_shift->setRange(0, 16);
391  bit_shift->setValue(d.bit_shift);
392  table->setCellWidget(table->rowCount() - 1, 3, bit_shift);
393 }
394 
395 void ModbusTCPHandler::addUInt8(const industrial_modbus_tcp::UInt8 &d)
396 {
397  QTableWidget *table(tables_.at(UINT8));
398  table->insertRow(table->rowCount());
399  addRegister(d.reg, table);
400 
401  QSpinBox *bit_shift(new QSpinBox);
402  bit_shift->setRange(0, 16);
403  bit_shift->setValue(d.bit_shift);
404  table->setCellWidget(table->rowCount() - 1, 3, bit_shift);
405 }
406 
407 void ModbusTCPHandler::addInt16(const industrial_modbus_tcp::Int16 &d)
408 {
409  QTableWidget *table(tables_.at(INT16));
410  table->insertRow(table->rowCount());
411  addRegister(d.reg, table);
412 }
413 
414 void ModbusTCPHandler::addUInt16(const industrial_modbus_tcp::UInt16 &d)
415 {
416  QTableWidget *table(tables_.at(UINT16));
417  table->insertRow(table->rowCount());
418  addRegister(d.reg, table);
419 }
420 
421 void ModbusTCPHandler::addInt32(const industrial_modbus_tcp::Int32 &d)
422 {
423  QTableWidget *table(tables_.at(INT32));
424  table->insertRow(table->rowCount());
425  addRegister(d.reg, table);
426  addBigEndian(d.big_endian, table);
427 }
428 
429 void ModbusTCPHandler::addUInt32(const industrial_modbus_tcp::UInt32 &d)
430 {
431  QTableWidget *table(tables_.at(UINT32));
432  table->insertRow(table->rowCount());
433  addRegister(d.reg, table);
434  addBigEndian(d.big_endian, table);
435 }
436 
437 void ModbusTCPHandler::addInt64(const industrial_modbus_tcp::Int64 &d)
438 {
439  QTableWidget *table(tables_.at(INT64));
440  table->insertRow(table->rowCount());
441  addRegister(d.reg, table);
442  addBigEndian(d.big_endian, table);
443 }
444 
445 void ModbusTCPHandler::addUInt64(const industrial_modbus_tcp::UInt64 &d)
446 {
447  QTableWidget *table(tables_.at(UINT64));
448  table->insertRow(table->rowCount());
449  addRegister(d.reg, table);
450  addBigEndian(d.big_endian, table);
451 }
452 
453 void ModbusTCPHandler::addFloat32(const industrial_modbus_tcp::Float32 &d)
454 {
455  QTableWidget *table(tables_.at(FLOAT32));
456  table->insertRow(table->rowCount());
457  addRegister(d.reg, table);
458  addBigEndian(d.big_endian, table);
459 }
460 
461 void ModbusTCPHandler::addFloat64(const industrial_modbus_tcp::Float64 &d)
462 {
463  QTableWidget *table(tables_.at(FLOAT64));
464  table->insertRow(table->rowCount());
465  addRegister(d.reg, table);
466  addBigEndian(d.big_endian, table);
467 }
468 
470 {
471  switch (tabs_->currentIndex())
472  {
473  case BOOL:
474  {
475  industrial_modbus_tcp::Bool d;
476  d.reg.poll_rate_usec = 200000;
477  addBool(d);
478  break;
479  }
480  case INT8:
481  {
482  industrial_modbus_tcp::Int8 d;
483  d.reg.poll_rate_usec = 200000;
484  addInt8(d);
485  break;
486  }
487  case UINT8:
488  {
489  industrial_modbus_tcp::UInt8 d;
490  d.reg.poll_rate_usec = 200000;
491  addUInt8(d);
492  break;
493  }
494  case INT16:
495  {
496  industrial_modbus_tcp::Int16 d;
497  d.reg.poll_rate_usec = 200000;
498  addInt16(d);
499  break;
500  }
501  case UINT16:
502  {
503  industrial_modbus_tcp::UInt16 d;
504  d.reg.poll_rate_usec = 200000;
505  addUInt16(d);
506  break;
507  }
508  case INT32:
509  {
510  industrial_modbus_tcp::Int32 d;
511  d.reg.poll_rate_usec = 200000;
512  addInt32(d);
513  break;
514  }
515  case UINT32:
516  {
517  industrial_modbus_tcp::UInt32 d;
518  d.reg.poll_rate_usec = 200000;
519  addUInt32(d);
520  break;
521  }
522  case INT64:
523  {
524  industrial_modbus_tcp::Int64 d;
525  d.reg.poll_rate_usec = 200000;
526  addInt64(d);
527  break;
528  }
529  case UINT64:
530  {
531  industrial_modbus_tcp::UInt64 d;
532  d.reg.poll_rate_usec = 200000;
533  addUInt64(d);
534  break;
535  }
536  case FLOAT32:
537  {
538  industrial_modbus_tcp::Float32 d;
539  d.reg.poll_rate_usec = 200000;
540  addFloat32(d);
541  break;
542  }
543  case FLOAT64:
544  {
545  industrial_modbus_tcp::Float64 d;
546  addFloat64(d);
547  break;
548  }
549  default:
550  break;
551  }
552 }
553 
555 {
556  QTableWidget *table(tables_.at(tabs_->currentIndex()));
557  table->removeRow(table->rowCount() - 1);
558 }
559 
560 }
d
ModbusTCPHandler(industrial_modbus_tcp::ModbusHandler h=industrial_modbus_tcp::ModbusHandler())
void addBigEndian(const bool value, QTableWidget *table)
industrial_modbus_tcp::ModbusHandler getHandler()
void addInt32(const industrial_modbus_tcp::Int32 &d)
void addInt64(const industrial_modbus_tcp::Int64 &d)
void addUInt64(const industrial_modbus_tcp::UInt64 &d)
void addFloat32(const industrial_modbus_tcp::Float32 &d)
std::vector< QTableWidget * > tables_
void addFloat64(const industrial_modbus_tcp::Float64 &d)
void addInt8(const industrial_modbus_tcp::Int8 &d)
void addInt16(const industrial_modbus_tcp::Int16 &d)
void addRegister(const industrial_modbus_tcp::Register &r, QTableWidget *table)
void addUInt8(const industrial_modbus_tcp::UInt8 &d)
void readRegisterTable(const QTableWidget *table, const unsigned row, industrial_modbus_tcp::Register &r)
void addUInt32(const industrial_modbus_tcp::UInt32 &d)
void addUInt16(const industrial_modbus_tcp::UInt16 &d)
void addBool(const industrial_modbus_tcp::Bool &d)


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