Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c76baa9
Include stdexcept header to fix compiler errors
olereinhardt Aug 2, 2021
8db93a5
rtu layer: fix parsing of settings string
tamara-schmitz Dec 12, 2024
da9f2f0
Add ReleaseWithDoc project settings
epsilonrt Apr 5, 2020
a0b862a
move configure_file call for config.h behind all check_symbol_exists …
Jun 23, 2021
fe0438d
adjust all defines and function call to libmodbus-ascii-support
Jun 23, 2021
0cb6ff5
ascii support is only available in the custom libmodbusepsi starting …
Jun 23, 2021
3daeb94
Create a copy of RTU Layer as a starting poiont for building the ASCI…
Jun 23, 2021
eb1966f
use the recv_filter flag also for ASCII mode
Jun 24, 2021
9c63d31
implement quick n dirty ascii layer functionality
Jun 24, 2021
b62858c
remove the modbusepsi include path from CFLAGS and use a relative pat…
Jun 25, 2021
68009b4
make the installation of codelite templates optional with cmake optio…
Jun 25, 2021
42f859a
[async] fix race condition if destroy server object while call async …
Oct 18, 2021
e19ea3f
[message] change Callback from simple pointer to std::function; enabl…
Oct 25, 2021
d20311e
[data] make method Data::updateValues public
Nov 2, 2021
c6bfe7a
make pointer to Private NetLayer implementation a unique_ptr, also ma…
Nov 24, 2021
9e679cd
make pointer to Private Device implementation a unique_ptr
Nov 24, 2021
61cc8d2
enable tcp server to handle multiple client connections
Nov 24, 2021
c00c7d9
set working dir of GitVersion to source dir; this helps with out of s…
Jan 11, 2022
a81892c
[server] allow access to file descriptors, so the user can handle mul…
Feb 3, 2022
8125121
re-added virtual destructors to prevent memory leaks
Sep 11, 2025
fc34a08
Merge pull request #1 from DennisPurdack/libmodbuspp-ascii-support
fboor Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,11 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

set(LIBMODBUS_MIN_VERSION "3.1.6")
set(LIBMODBUS_MIN_VERSION "3.1.10")
find_package(PkgConfig REQUIRED)

pkg_check_modules (LIBMODBUS libmodbusepsi>=${LIBMODBUS_MIN_VERSION})
if (LIBMODBUS_FOUND)
set(LIBMODBUS_NAME modbusepsi)
else()
pkg_check_modules (LIBMODBUS REQUIRED libmodbus>=${LIBMODBUS_MIN_VERSION})
set(LIBMODBUS_NAME modbus)
endif()
pkg_check_modules (LIBMODBUS REQUIRED libmodbusepsi>=${LIBMODBUS_MIN_VERSION})
set(LIBMODBUS_NAME modbusepsi)

set(LIBMODBUS_PACKAGE lib${LIBMODBUS_NAME}5)
set(LIBMODBUSDEV_PACKAGE lib${LIBMODBUS_NAME}-dev)
Expand All @@ -98,7 +93,7 @@ else()
add_subdirectory(3rdparty/json)
endif()

set (MODBUSPP_CFLAGS_OTHER ${CMAKE_THREAD_LIBS_INIT} ${LIBMODBUS_CFLAGS})
set (MODBUSPP_CFLAGS_OTHER ${CMAKE_THREAD_LIBS_INIT})
set (MODBUSPP_LDFLAGS_OTHER ${LIBMODBUS_LDFLAGS} -lpthread)

include (GetDate)
Expand All @@ -108,8 +103,6 @@ include (GitVersion)
GetGitVersion(MODBUSPP_VERSION)
set(MODBUSPP_VERSION
${MODBUSPP_VERSION_MAJOR}.${MODBUSPP_VERSION_MINOR}.${MODBUSPP_VERSION_PATCH})
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY)

Expand All @@ -125,7 +118,10 @@ check_symbol_exists(TIOCSRS485 sys/ioctl.h MODBUSPP_HAVE_TIOCRS485)
check_symbol_exists(TIOCM_RTS sys/ioctl.h MODBUSPP_HAVE_TIOCM_RTS)

list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBMODBUS_NAME})
check_symbol_exists(modbus_rtu_set_recv_filter ${LIBMODBUS_NAME}/modbus-rtu.h MODBUSPP_HAVE_RTU_MULTI_SLAVES)
check_symbol_exists(modbus_serial_set_recv_filter ${LIBMODBUS_NAME}/modbus-serial.h MODBUSPP_HAVE_SERIAL_MULTI_SLAVES)

configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)

# Make relative paths absolute (needed later on)
foreach(p LIB BIN INCLUDE CMAKE DATA DOC CODELITE)
Expand Down Expand Up @@ -307,7 +303,7 @@ if (CPACK_GENERATOR STREQUAL "DEB")
set(CPACK_DEBIAN_DEV_PACKAGE_NAME "libmodbuspp-dev")
set(CPACK_COMPONENT_DEV_DESCRIPTION "${CPACK_DEBIAN_LIB_PACKAGE_NAME} - ${PROJECT_DESCRIPTION} (development files)\n${PROJECT_DESCRIPTION_TEXT}\n This package provides the development files.")
set(CPACK_DEBIAN_DEV_FILE_NAME "lib${PROJECT_NAME}-dev_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (= ${CPACK_PACKAGE_VERSION}),pkg-config,git-core,${LIBMODBUSDEV_PACKAGE} (>= ${LIBMODBUS_VERSION})")
set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (= ${CPACK_PACKAGE_VERSION}),pkg-fconfig,git-core,${LIBMODBUSDEV_PACKAGE} (>= ${LIBMODBUS_VERSION})")
set(CPACK_DEBIAN_DEV_PACKAGE_SECTION "libdevel")
#set(CPACK_PACKAGE_DESCRIPTION_FILE "${MODBUSPP_SRC_DIR}/doc/README-deb.md")

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ _"Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless CRC
To benefit from the routing capacity of the Router and Server classes in RTU,
you must therefore use the fork of libmodbus named **libmodbusepsi**.
In this fork released from the [piduino](http://apt.piduino.org)
repository, filtering can be disabled (with _modbus_rtu_set_recv_filter()_).
repository, filtering can be disabled (with _modbus_serial_set_recv_filter()_).
Thus, it is the Server class which performs this filtering (after checking the
CRC therefore). Effectively, this has the effect of loading the microprocessor,
but, at present, the computing power of our machines is such that it does not
Expand Down
2 changes: 1 addition & 1 deletion config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
#include "version.h"
#cmakedefine01 MODBUSPP_HAVE_TIOCRS485
#cmakedefine01 MODBUSPP_HAVE_TIOCM_RTS
#cmakedefine01 MODBUSPP_HAVE_RTU_MULTI_SLAVES
#cmakedefine01 MODBUSPP_HAVE_SERIAL_MULTI_SLAVES

/* ========================================================================== */
4 changes: 4 additions & 0 deletions dev/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

cmake_minimum_required(VERSION 2.8.11)

option(INSTALL_TEMPLATES "Install codelite project templates to /usr/share/codelite" OFF)

if(INSTALL_TEMPLATES)
# set packaging dir
if(NOT CPACK_PACKAGE_DIRECTORY)
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages)
Expand All @@ -37,3 +40,4 @@ install (DIRECTORY codelite/unit-test-modbuspp
DIRECTORY_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
COMPONENT dev
)
endif(INSTALL_TEMPLATES)
4 changes: 3 additions & 1 deletion dev/cmake/GitVersion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ function(GetGitVersion _prefix)

if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} describe
RESULT_VARIABLE ret OUTPUT_VARIABLE str OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE ret
OUTPUT_VARIABLE str OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
endif()

Expand Down
1 change: 1 addition & 0 deletions include/modbuspp.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include <modbuspp/rtulayer.h>
#include <modbuspp/asciilayer.h>
#include <modbuspp/tcplayer.h>
#include <modbuspp/master.h>
#include <modbuspp/server.h>
Expand Down
211 changes: 211 additions & 0 deletions include/modbuspp/asciilayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/* Copyright © 2018-2019 Pascal JEAN, All rights reserved.
* This file is part of the libmodbuspp Library.
*
* The libmodbuspp Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* The libmodbuspp Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the libmodbuspp Library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <modbuspp/netlayer.h>

namespace Modbus {

/**
* @class AsciiLayer
* @brief RTU serial link layer
*
* This class can not and should not be instantiated by the user.
* It provides access to properties and methods specific to the RTU layer.
*
* An instance of this class is created by the constructor @b Device::Device()
* of the @b Device class (or its derived classes) if the RTU layer is selected.
*
* Access to this instance is done using the Device::rtu() method.
*
* @sa Device::Device()
* @sa Device::rtu()
*
* @author Pascal JEAN, aka epsilonrt
* @copyright GNU Lesser General Public License
*/
class AsciiLayer : public NetLayer {
public:

/**
* @brief Constructor
*/
AsciiLayer (const std::string & port, const std::string & settings);

/**
* @brief Destructor
*/
virtual ~AsciiLayer() = default;

/**
* @brief Name of the serial port
*
* This property specifies the name of the serial port handled by the
* OS, eg. "/dev/ttyS0" or "/dev/ttyUSB0".
*/
const std::string & port() const;

/**
* @brief Return the baudrate
*/
int baud() const;

/**
* @brief Return the parity
*/
char parity() const;

/**
* @brief Return the bits of stop
*/
int stop() const;

/**
* @brief Get the current serial mode
*
* This function shall return the serial mode currently used.
*
* - @b Rs232: the serial line is set for RS232 communication. RS-232
* (Recommended Standard 232) is the traditional name for a series of
* standards for serial binary single-ended data and control signals
* connecting between a DTE (Data Terminal Equipment) and a DCE
* (Data Circuit-terminating Equipment).
* It is commonly used in computer serial ports
* - @b Rs485: the serial line is set for RS485 communication. EIA-485,
* also known as TIA/EIA-485 or RS-485, is a standard defining the electrical
* characteristics of drivers and receivers for use in balanced digital
* multipoint systems. This standard is widely used for communications in
* industrial automation because it can be used effectively over long
* distances and in electrically noisy environments.
* .
* This function is only available on Linux kernels 2.6.28 onwards.
*
* @return return the current mode if successful.
* Otherwise it shall return @b UnknownMode (-1) and set errno.
* @sa setSerialMode()
*/
SerialMode serialMode();

/**
* @brief Set the serial mode
*
* This function shall set the selected serial mode @b mode.
*
* @return true if successful.
* Otherwise it shall return false and set errno.
* @sa serialMode()
*/
bool setSerialMode (SerialMode mode);

/**
* @brief Get the current RTS mode
*
* This function shall get the current Request To Send mode
*
* @return the current RTS mode if successful.
* Otherwise it shall return @b UnknownRts (-1) and set errno.
* @sa setRts()
*/
SerialRts rts();

/**
* @brief Set the RTS mode
*
* This function shall set the Request To Send mode to communicate on a
* RS485 serial bus.
*
* @return true if successful.
* Otherwise it shall return false and set errno.
* @sa rts()
*/
bool setRts (SerialRts rts);

/**
* @brief Get the current RTS delay
*
* This function shall get the current Request To Send delay period.
* @return the current RTS delay in microseconds if successful.
* Otherwise it shall return -1 and set errno.
* @sa setRtsDelay()
*/
int rtsDelay();

/**
* @brief Set the RTS delay
*
* This function shall set the Request To Send delay period in microseconds.
*
* @return true if successful.
* Otherwise it shall return false and set errno.
* @sa rtsDelay()
*/
bool setRtsDelay (int us);

/**
* @overload
*
* @warning This function is not supported by Windows !
*/
virtual int sendRawMessage (const Message * msg);

/**
* @overload
*/
virtual bool prepareToSend (Message & msg);

/**
* @overload
*/
static bool checkMessage (const Message & msg);

/**
* @brief Extracts the baudrate from a settings string.
* @return the baudrate found. if no value is found, returns the default
* value, ie 19200.
*/
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.
*/
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.
*/
static int stop (const std::string & settings);

/**
* @brief Performing Modbus CRC16 generation of the buffer @b buf
*/
static uint8_t lrc8 (const uint8_t * buffer, uint16_t buffer_length);

protected:
class Private;
AsciiLayer (std::unique_ptr<Private> &&dd);

private:
PIMP_DECLARE_PRIVATE (AsciiLayer)
};
}

/* ========================================================================== */
26 changes: 14 additions & 12 deletions include/modbuspp/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
#pragma once

#include <stdexcept>
#include <cstdio> // printf
#include <cstring> // memcpy ...
#include <array>
Expand Down Expand Up @@ -219,6 +220,19 @@ namespace Modbus {
print ( (const uint8_t *) m_registers.data(), size());
}

// update data value from MODBUS registers
// to call after reading the modbus registers
void updateValue() {
T v;

for (auto & r : m_registers) {
r = hton (r);
}
std::memcpy (&v, m_registers.data(), sizeof (T));
swap (v);
m_value = ntoh (v);
}

friend class Slave;
friend class BufferedSlave;
friend class Message;
Expand All @@ -241,18 +255,6 @@ namespace Modbus {
}
}

// update data value from MODBUS registers
// to call after reading the modbus registers
void updateValue() {
T v;

for (auto & r : m_registers) {
r = hton (r);
}
std::memcpy (&v, m_registers.data(), sizeof (T));
swap (v);
m_value = ntoh (v);
}
#endif /* __DOXYGEN__ not defined */

private:
Expand Down
Loading