modbuspp  1.1.40
C++ wrapper for the libmodbus library
router/router-simple/main.cpp
#include <csignal>
#include <thread>
#include <iostream>
#include <modbuspp.h>
#include <modbuspp/popl.h>
using namespace std;
using namespace Modbus;
Router router; // instantiates new MODBUS Router
// -----------------------------------------------------------------------------
// Signal trap, triggers during a CTRL+C or if kill is called
void
sighandler (int sig) {
router.close();
cout << "everything was closed." << endl << "Have a nice day !" << endl;
}
// -----------------------------------------------------------------------------
int main (int argc, char **argv) {
string host;
string port;
string serial;
string settings;
// parsing options from the command line
// watch https://github.com/badaix/popl to understand how we use popl ...
popl::OptionParser CmdLine ("Allowed options");
auto help_option = CmdLine.add<popl::Switch> ("h", "help", "produce help message");
CmdLine.add<popl::Value<string>> ("H", "host", "listening address of the server", "127.0.0.1", &host);
CmdLine.add<popl::Value<string>> ("p", "port", "server listening port", "1502", &port);
CmdLine.add<popl::Value<string>> ("P", "serial", "serial port", "/dev/ttyUSB0", &serial);
CmdLine.add<popl::Value<string>> ("s", "settings", "serial port settings", "38400E1", &settings);
auto rs485_option = CmdLine.add<popl::Switch> ("R", "rs485", "RS-485 mode (/RTS on (0) after sending)");
cout << "--- Modbus Router ---" << endl;
// CTRL+C and kill call triggers the trap sighandler()
signal (SIGINT, sighandler);
signal (SIGTERM, sighandler);
cout << "Press CTRL+C to stop... " << endl;
try {
CmdLine.parse (argc, argv);
// print auto-generated help message then exit
if (help_option->count() == 1) {
cout << CmdLine << endl;
exit (EXIT_SUCCESS);
}
router.setBackend (Tcp, host, port);
// Enabling debug mode to display transmitted and received frames
router.setDebug();
// Activation of automatic reconnection mode
// If this option is enabled, the server is restarted after each
// disconnection of a client over TCP.
router.setRecoveryLink();
// Creating the MODBUS master link that controls the serial link
Master & inside = router.addMaster ("inside", Rtu, serial, settings);
inside.setDebug();
if (rs485_option->count() == 1) {
inside.rtu().setRts (RtsDown);
inside.rtu().setSerialMode (Rs485);
}
// Declaration of a slave with the address 33 accessible via the TCP server
// and physically connected to the serial link managed by inside
// Be sure to set press as a reference (&) because the BufferedSlave
// variable itself is owned by the router.
BufferedSlave & press = router.addSlave (33, &inside);
// Declaration of the input register block of the press slave, it has
// 6 registers, of which the following description is :
// @ Reg. Size Sensor Description
// 1 16-bit MPX Pressure measured in tenths of hPa, unsigned integer
// 2 16-bit HSC Pressure measured in tenths of hPa, unsigned integer
// 3 16-bit HSC Temperature measured in hundredths of °C, signed integer
// 4 16-bit MPX Raw ADC value of pressure in LSB, unsigned integer
// 5 16-bit HSC HSC raw value of pressure in LSB, unsigned integer
// 6 16-bit HSC HSC raw value of temperature in LSB, unsigned integer
press.setBlock (InputRegister, 6);
// Declaration of the block of holding registers of the press slave,
// it comprises 4 registers 32-bit, thus 8 registers 16-bit, here is
// the description :
// @ Reg. Size Sensor Description Default
// 1 32-bit MPX Minimum standard pressure, float in hPa 150
// 3 32-bit MPX Maximum standard pressure, float in hPa 1150
// 5 32-bit MPX Minimum standard ADC value, float in LSB ADC 40.96
// 7 32-bit MPX Maximum ADC standard value, float in LSB ADC 962.56
press.setBlock (HoldingRegister, 8); // 32-bit * 4
// We do the same thing with the humidity sensor at address 32, this slave
// has only 2 input registers.
BufferedSlave & hum = router.addSlave (32, &inside);
hum.setBlock (InputRegister, 2);
hum.setBlock (HoldingRegister, 8); // 32-bit * 4
if (router.open ()) { // open a connection
cout << "Listening server on " <<
router.connection() << ":" << router.settings() << "..."
<< endl << endl;
router.run();
while (router.isOpen()) {
//std::this_thread::yield();
std::this_thread::sleep_for (std::chrono::milliseconds (200));
}
}
}
catch (std::exception & e) {
cerr << "Error: " << e.what() << endl;
}
catch (...) {
cerr << "Unattended exception !" << endl;
}
return EXIT_FAILURE;
}
/* ========================================================================== */