From c76baa99f9e6566bc0fb92672454c2d013d790f5 Mon Sep 17 00:00:00 2001 From: Ole Reinhardt Date: Mon, 2 Aug 2021 17:05:03 +0200 Subject: [PATCH 1/2] Include stdexcept header to fix compiler errors --- include/modbuspp/data.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/modbuspp/data.h b/include/modbuspp/data.h index 49aca7c..2ef97a7 100644 --- a/include/modbuspp/data.h +++ b/include/modbuspp/data.h @@ -16,6 +16,7 @@ */ #pragma once +#include #include // printf #include // memcpy ... #include From 8db93a5d78f95e1641c89db5f54cf85b671c0e93 Mon Sep 17 00:00:00 2001 From: Tamara Schmitz Date: Thu, 12 Dec 2024 17:23:21 +0100 Subject: [PATCH 2/2] rtu layer: fix parsing of settings string Throw exceptions on error instead of silently changing values. Check settings string for given stop bit value. Up until now, the stop bits value was hard coded to be 2 if the parity mode was set to none or 1 if the parity mode was set to even or odd. So a setting of "115200E1" would result in a stop bit value of 1. But "115200E2" would result also in a stop bit value of 1. And "115200N1" would result in a stop bit value of 2. This is not a restriction of libmodbus. The library supports all these modes just fine. In fact they are using 115200N1 in the documentation for modbus_new_rtu(). Rather this is a bug in the string parsing that libmodbuspp introduces in its constructor. libmodbus has no string parsing in modbus_new_rtu() and takes in the arguments as parameters directly. Fixes: b0f3dc4be5e82729825158ca651657afe1f6380b --- include/modbuspp/rtulayer.h | 11 +++++------ src/rtulayer.cpp | 32 ++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/include/modbuspp/rtulayer.h b/include/modbuspp/rtulayer.h index eac2b5f..6634911 100644 --- a/include/modbuspp/rtulayer.h +++ b/include/modbuspp/rtulayer.h @@ -169,23 +169,22 @@ namespace Modbus { /** * @brief Extracts the baudrate from a settings string. - * @return the baudrate found. if no value is found, returns the default - * value, ie 19200. + * @return the baudrate found. If no valid value is found, an exception is thrown. */ static int baud (const std::string & settings); /** * @brief Extracts the parity from a settings string. - * @return the parity found. if no value is found, returns the default - * value, ie E for Even parity. + * @return the parity found. If no valid value is found, an exception is thrown. */ static char parity (const std::string & settings); /** * @brief Return the stop bits from a settings string. * - * @return the number returned is determined based on the parity found. - * If the parity is None, this function returns 2, otherwise returns 1. + * @return the number of stop bits. + * It is parsed from the last character of the settings string. + * If the last character is neither '1' or '2' an exception is thrown. */ static int stop (const std::string & settings); diff --git a/src/rtulayer.cpp b/src/rtulayer.cpp index 6c265c5..dad21ac 100644 --- a/src/rtulayer.cpp +++ b/src/rtulayer.cpp @@ -234,40 +234,48 @@ namespace Modbus { // --------------------------------------------------------------------------- // static int RtuLayer::baud (const std::string & settings) { - int b; try { - b = std::stoi (settings); + return std::stoi (settings); } catch (...) { - b = 19200; + throw std::invalid_argument ("RtuLayer settings\"" + settings + "\" has an invalid baud rate setting."); } - return b; } // --------------------------------------------------------------------------- // static char RtuLayer::parity (const std::string & settings) { - char p = 'N'; size_t s = settings.length(); if (s >= 2) { char c = settings[s - 2]; - if ( (c == 'E') || (c == 'O')) { - return c; + switch (c) { + case 'N': + case 'E': + case 'O': + return c; } } - return p; + + throw std::invalid_argument ("RtuLayer settings\"" + settings + "\" has an invalid parity setting."); } // --------------------------------------------------------------------------- // static int RtuLayer::stop (const std::string & settings) { + size_t s = settings.length(); - if (parity (settings) == 'N') { - - return 2; + if (s >= 3) { + char c = settings[s - 1]; + switch (c) { + case '1': + return 1; + case '2': + return 2; + } } - return 1; + + throw std::invalid_argument ("RtuLayer settings\"" + settings + "\" has an invalid stop bit setting."); } // ---------------------------------------------------------------------------