Commit d87350fb56e904d3a0eb67e4011dcb42b9ece8bc
Committed by
GitHub
Merge pull request #2 from pgroen/feat/pgroen/modbus-rtu-implementation
Feat/pgroen/modbus rtu implementation
Showing
11 changed files
with
248 additions
and
25 deletions
CMakeLists.txt
src/connectionconfig.h
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | #pragma once | 7 | #pragma once |
| 8 | 8 | ||
| 9 | #include <string> | 9 | #include <string> |
| 10 | +#include <termios.h> | ||
| 10 | 11 | ||
| 11 | namespace osdev { | 12 | namespace osdev { |
| 12 | namespace components { | 13 | namespace components { |
| @@ -29,27 +30,17 @@ public: | @@ -29,27 +30,17 @@ public: | ||
| 29 | NONE | 30 | NONE |
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | - enum class E_BAUDRATE | ||
| 33 | - { | ||
| 34 | - R1200 = 1200, | ||
| 35 | - R2400 = 2400, | ||
| 36 | - R4800 = 4800, | ||
| 37 | - R9600 = 9600, | ||
| 38 | - R19200 = 19200, | ||
| 39 | - R38400 = 38400, | ||
| 40 | - R57600 = 57600, | ||
| 41 | - R76800 = 76800, | ||
| 42 | - R115200 = 115200 | ||
| 43 | - }; | ||
| 44 | - | ||
| 45 | ConnectionConfig(); | 33 | ConnectionConfig(); |
| 46 | 34 | ||
| 47 | // Getters and Setters | 35 | // Getters and Setters |
| 48 | void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; } | 36 | void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; } |
| 49 | E_CONNECTIONTYPE getConnectionType() const { return m_conType; } | 37 | E_CONNECTIONTYPE getConnectionType() const { return m_conType; } |
| 50 | 38 | ||
| 51 | - void setBaudRate( E_BAUDRATE baud_rate ) { m_baudRate = baud_rate; } | ||
| 52 | - E_BAUDRATE getBaudRate() const { return m_baudRate; } | 39 | + void setPortName(const std::string &port_name) { m_portName = port_name; } |
| 40 | + std::string getPortName() { return m_portName; } | ||
| 41 | + | ||
| 42 | + void setBaudRate( speed_t baud_rate ) { m_baudRate = baud_rate; } | ||
| 43 | + speed_t getBaudRate() const { return m_baudRate; } | ||
| 53 | 44 | ||
| 54 | void setParity(E_PARITY parity) { m_parity = parity; } | 45 | void setParity(E_PARITY parity) { m_parity = parity; } |
| 55 | E_PARITY getParity() const { return m_parity; } | 46 | E_PARITY getParity() const { return m_parity; } |
| @@ -70,14 +61,15 @@ public: | @@ -70,14 +61,15 @@ public: | ||
| 70 | int getFrameTimeout() const { return m_frameTimeOut; } | 61 | int getFrameTimeout() const { return m_frameTimeOut; } |
| 71 | 62 | ||
| 72 | private: | 63 | private: |
| 73 | - E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN; | ||
| 74 | - E_BAUDRATE m_baudRate = E_BAUDRATE::R9600; | ||
| 75 | - E_PARITY m_parity = E_PARITY::NONE; | ||
| 76 | - int m_dataBits = 8; | ||
| 77 | - int m_stopBits = 1; | ||
| 78 | - std::string m_ipAddress{}; | ||
| 79 | - unsigned int m_portNumber = 502; | ||
| 80 | - int m_frameTimeOut = -1; | 64 | + E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN; |
| 65 | + std::string m_portName = "/dev/ttyUSB0"; | ||
| 66 | + speed_t m_baudRate = B9600; | ||
| 67 | + E_PARITY m_parity = E_PARITY::NONE; | ||
| 68 | + int m_dataBits = 8; | ||
| 69 | + int m_stopBits = 1; | ||
| 70 | + std::string m_ipAddress{}; | ||
| 71 | + unsigned int m_portNumber = 502; | ||
| 72 | + int m_frameTimeOut = -1; | ||
| 81 | 73 | ||
| 82 | }; | 74 | }; |
| 83 | 75 |
src/modbusbase.h
| @@ -57,8 +57,8 @@ namespace modbus { | @@ -57,8 +57,8 @@ namespace modbus { | ||
| 57 | class ModbusBase | 57 | class ModbusBase |
| 58 | { | 58 | { |
| 59 | public: | 59 | public: |
| 60 | - ModbusBase(); | ||
| 61 | - virtual ~ModbusBase(); | 60 | + ModbusBase() {} |
| 61 | + virtual ~ModbusBase() {} | ||
| 62 | 62 | ||
| 63 | // Pure virtuals. Override when inherited. | 63 | // Pure virtuals. Override when inherited. |
| 64 | virtual bool Connect() = 0; | 64 | virtual bool Connect() = 0; |
src/modbusrtu.cpp
| @@ -4,3 +4,96 @@ | @@ -4,3 +4,96 @@ | ||
| 4 | * This source code is licensed under the MIT license found in the | 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. | 5 | * LICENSE file in the root directory of this source tree. |
| 6 | */ | 6 | */ |
| 7 | + | ||
| 8 | +#include "modbusrtu.h" | ||
| 9 | + | ||
| 10 | +#include <stdio.h> | ||
| 11 | + | ||
| 12 | +// Linux headers | ||
| 13 | +#include <fcntl.h> // Contains file controls like O_RDWR | ||
| 14 | +#include <errno.h> // Error integer and strerror() function | ||
| 15 | +#include <termios.h> // Contains POSIX terminal control definitions | ||
| 16 | +#include <unistd.h> // write(), read(), close() | ||
| 17 | + | ||
| 18 | +using namespace osdev::components::modbus; | ||
| 19 | + | ||
| 20 | +ModbusRtu::ModbusRtu( const ConnectionConfig &conf ) | ||
| 21 | + : m_conConfig( conf ) | ||
| 22 | + , m_socket( -1 ) | ||
| 23 | +{ | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +bool ModbusRtu::Connect() | ||
| 27 | +{ | ||
| 28 | + m_socket = open( m_conConfig.getPortName().c_str(), O_RDWR); | ||
| 29 | + if(m_socket == -1) | ||
| 30 | + { | ||
| 31 | + return false; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + struct termios l_tty; | ||
| 35 | + | ||
| 36 | + // Read in existing settings, and handle any error | ||
| 37 | + if( tcgetattr(m_socket, &l_tty) != 0 ) | ||
| 38 | + { | ||
| 39 | + // Replace later on with a logger line. | ||
| 40 | + return false; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /* Control modes */ | ||
| 44 | + l_tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common) | ||
| 45 | + l_tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common) | ||
| 46 | + l_tty.c_cflag &= ~CSIZE; // Clear all bits that set the data field | ||
| 47 | + l_tty.c_cflag |= CS8; // 8 bits per byte (most common) | ||
| 48 | + l_tty.c_cflag &= ~CRTSCTS; // Disable RTS / CTS hardware flow control (most common) | ||
| 49 | + l_tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) | ||
| 50 | + | ||
| 51 | + /* local modes */ | ||
| 52 | + l_tty.c_lflag &= ~ICANON; // Something, something CANONICAL.. Something, something Dark Side.... | ||
| 53 | + l_tty.c_lflag &= ~ECHO; // Disable echo | ||
| 54 | + l_tty.c_lflag &= ~ECHOE; // Disable Erasure | ||
| 55 | + l_tty.c_lflag &= ~ECHONL; // Diasble new-line echo | ||
| 56 | + l_tty.c_lflag &= ~ISIG; // Disable interpretation of INTS, QUIT and SUSP | ||
| 57 | + l_tty.c_lflag &= ~(IXON | IXOFF | IXANY ); // Turn off s/w flow control | ||
| 58 | + | ||
| 59 | + /* Ouput modes */ | ||
| 60 | + l_tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) | ||
| 61 | + l_tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed | ||
| 62 | + | ||
| 63 | + // Wait for up to 1 seconds ( 10 deciseconds), returning as soon as any data is received. | ||
| 64 | + l_tty.c_cc[VTIME] = 10; | ||
| 65 | + l_tty.c_cc[VMIN] = 0; | ||
| 66 | + | ||
| 67 | + // Set the read and write baudrate. | ||
| 68 | + cfsetispeed(&l_tty, m_conConfig.getBaudRate()); | ||
| 69 | + cfsetospeed(&l_tty, m_conConfig.getBaudRate()); | ||
| 70 | + | ||
| 71 | + // Save the tty settings. | ||
| 72 | + if( tcsetattr(m_socket, TCSANOW, &l_tty) != 0 ) | ||
| 73 | + { | ||
| 74 | + Close(); | ||
| 75 | + return false; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + return true; | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +bool ModbusRtu::Close() | ||
| 82 | +{ | ||
| 83 | + if( close(m_socket) != 0 ) | ||
| 84 | + { | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + return true; | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +int ModbusRtu::modbusSend(uint8_t *to_send, size_t length) | ||
| 91 | +{ | ||
| 92 | + return write(m_socket, to_send, length); | ||
| 93 | + | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +int ModbusRtu::modbusReceive(uint8_t *buffer) | ||
| 97 | +{ | ||
| 98 | + return read(m_socket, buffer, sizeof(*buffer)); | ||
| 99 | +} |
src/modbusrtu.h
| @@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "modbusbase.h" | 8 | #include "modbusbase.h" |
| 9 | +#include "connectionconfig.h" | ||
| 9 | 10 | ||
| 10 | namespace osdev { | 11 | namespace osdev { |
| 11 | namespace components { | 12 | namespace components { |
| @@ -13,7 +14,31 @@ namespace modbus { | @@ -13,7 +14,31 @@ namespace modbus { | ||
| 13 | 14 | ||
| 14 | class ModbusRtu : public ModbusBase | 15 | class ModbusRtu : public ModbusBase |
| 15 | { | 16 | { |
| 17 | +public: | ||
| 18 | + explicit ModbusRtu( const ConnectionConfig &conf ); | ||
| 19 | + virtual ~ModbusRtu() {} | ||
| 16 | 20 | ||
| 21 | + virtual bool Connect() override; | ||
| 22 | + virtual bool Close() override; | ||
| 23 | + | ||
| 24 | + /*! | ||
| 25 | + * \brief modbusSend | ||
| 26 | + * \param to_send | ||
| 27 | + * \param length | ||
| 28 | + * \return | ||
| 29 | + */ | ||
| 30 | + virtual int modbusSend(uint8_t *to_send, size_t length) override; | ||
| 31 | + | ||
| 32 | + /*! | ||
| 33 | + * \brief modbusReceive | ||
| 34 | + * \param buffer | ||
| 35 | + * \return | ||
| 36 | + */ | ||
| 37 | + virtual int modbusReceive(uint8_t *buffer) override; | ||
| 38 | + | ||
| 39 | +private: | ||
| 40 | + ConnectionConfig m_conConfig; | ||
| 41 | + int m_socket; | ||
| 17 | }; | 42 | }; |
| 18 | 43 | ||
| 19 | } /* End namespace modbus */ | 44 | } /* End namespace modbus */ |
tests/CMakeLists.txt
0 → 100644
| 1 | +# **************************************************************** | ||
| 2 | +# Copyright (c)2022 Peter M. Groen | ||
| 3 | +# This file is licensed under the MIT license found in the | ||
| 4 | +# LICENSE file in the root directory of this source tree. | ||
| 5 | +# **************************************************************** | ||
| 6 | +add_executable(modbustest | ||
| 7 | + connectionconfigtest.cpp | ||
| 8 | +) | ||
| 9 | + | ||
| 10 | +target_include_directories(modbustest PRIVATE | ||
| 11 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 12 | + ${CMAKE_SOURCE_DIR}/include | ||
| 13 | + ${CMAKE_SOURCE_DIR}/src | ||
| 14 | + ${CMAKE_BINARY_DIR} | ||
| 15 | +) | ||
| 16 | + | ||
| 17 | +target_link_libraries(modbustest PRIVATE | ||
| 18 | + gmock_main | ||
| 19 | + gmock | ||
| 20 | + gtest | ||
| 21 | + modbus-cpp | ||
| 22 | +) | ||
| 23 | + | ||
| 24 | +add_test(NAME modbustest COMMAND modbustest) | ||
| 25 | + | ||
| 26 | +set_tests_properties(modbustest PROPERTIES | ||
| 27 | + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" | ||
| 28 | +) |
tests/connectionconfigtest.cpp
0 → 100644
| 1 | +/**************************************************************** | ||
| 2 | + * Copyright (c)2022 Peter M. Groen | ||
| 3 | + * This file is licensed under the MIT license found in the | ||
| 4 | + * LICENSE file in the root directory of this source tree. | ||
| 5 | + ****************************************************************/ | ||
| 6 | + | ||
| 7 | +#include <gmock/gmock.h> | ||
| 8 | +#include <gtest/gtest.h> | ||
| 9 | + | ||
| 10 | +#include "connectionconfig.h" | ||
| 11 | + | ||
| 12 | +using namespace osdev::components::modbus; | ||
| 13 | + | ||
| 14 | +TEST(ConnectionConfigTest, SerialPortConfig) | ||
| 15 | +{ | ||
| 16 | + ConnectionConfig oConfig; | ||
| 17 | + oConfig.setBaudRate( B9600 ); | ||
| 18 | + oConfig.setConnectionType( ConnectionConfig::E_CONNECTIONTYPE::SERIAL ); | ||
| 19 | + oConfig.setDataBits( 8 ); | ||
| 20 | + oConfig.setStopBits( 1 ); | ||
| 21 | + oConfig.setFrameTimeout( 10 ); | ||
| 22 | + oConfig.setParity( ConnectionConfig::E_PARITY::NONE ); | ||
| 23 | + oConfig.setPortName( "/dev/ttyUSB0" ); | ||
| 24 | + | ||
| 25 | + // Test all parameters | ||
| 26 | + | ||
| 27 | +} |
tools/CMakeLists.txt
0 → 100644
| 1 | +cmake_minimum_required(VERSION 3.0) | ||
| 2 | +project(modbus-cpp) | ||
| 3 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake) | ||
| 4 | + | ||
| 5 | +# ============================================================================== | ||
| 6 | +# = Include build information | ||
| 7 | +include(projectheader) | ||
| 8 | +project_header(modbus-cpp) | ||
| 9 | + | ||
| 10 | +add_subdirectory(modbus-master) | ||
| 11 | +# add_subdirectory(modbus-slave) |
tools/README.md
0 → 100644
tools/modbus-master/CMakeLists.txt
0 → 100644
tools/modbus-slave/CMakeLists.txt
0 → 100644
| 1 | +cmake_minimum_required(VERSION 3.16) | ||
| 2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake) | ||
| 3 | + | ||
| 4 | +include(projectheader) | ||
| 5 | +project_header(modbus-cpp) | ||
| 6 | + | ||
| 7 | +include(compiler) | ||
| 8 | + | ||
| 9 | +include_directories( | ||
| 10 | + ${CMAKE_SOURCE_DIR}/include | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +set(SRC_LIST | ||
| 14 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.h | ||
| 15 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.cpp | ||
| 16 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.h | ||
| 17 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.cpp | ||
| 18 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbusrtu.h | ||
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/modbusrtu.cpp | ||
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/connectionconfig.h | ||
| 21 | + ${CMAKE_CURRENT_SOURCE_DIR}/connectionconfig.cpp | ||
| 22 | +) | ||
| 23 | + | ||
| 24 | +include(library) | ||
| 25 | +add_libraries(PUBLIC | ||
| 26 | +) | ||
| 27 | + | ||
| 28 | +include(installation) | ||
| 29 | +install_component() | ||
| 30 | + |