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 | 7 | #pragma once |
| 8 | 8 | |
| 9 | 9 | #include <string> |
| 10 | +#include <termios.h> | |
| 10 | 11 | |
| 11 | 12 | namespace osdev { |
| 12 | 13 | namespace components { |
| ... | ... | @@ -29,27 +30,17 @@ public: |
| 29 | 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 | 33 | ConnectionConfig(); |
| 46 | 34 | |
| 47 | 35 | // Getters and Setters |
| 48 | 36 | void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; } |
| 49 | 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 | 45 | void setParity(E_PARITY parity) { m_parity = parity; } |
| 55 | 46 | E_PARITY getParity() const { return m_parity; } |
| ... | ... | @@ -70,14 +61,15 @@ public: |
| 70 | 61 | int getFrameTimeout() const { return m_frameTimeOut; } |
| 71 | 62 | |
| 72 | 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
src/modbusrtu.cpp
| ... | ... | @@ -4,3 +4,96 @@ |
| 4 | 4 | * This source code is licensed under the MIT license found in the |
| 5 | 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 | */ |
| 7 | 7 | |
| 8 | 8 | #include "modbusbase.h" |
| 9 | +#include "connectionconfig.h" | |
| 9 | 10 | |
| 10 | 11 | namespace osdev { |
| 11 | 12 | namespace components { |
| ... | ... | @@ -13,7 +14,31 @@ namespace modbus { |
| 13 | 14 | |
| 14 | 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 | 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
| 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-master) | |
| 6 | + | |
| 7 | +include(compiler) | |
| 8 | + | |
| 9 | +include_directories( | |
| 10 | + ${CMAKE_SOURCE_DIR}/include | |
| 11 | +) | |
| 12 | + | |
| 13 | +set(SRC_LIST | |
| 14 | +) | |
| 15 | + | ... | ... |
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 | + | ... | ... |