Commit d87350fb56e904d3a0eb67e4011dcb42b9ece8bc

Authored by Peter M. Groen
Committed by GitHub
2 parents 1bd935fb 40c6b751

Merge pull request #2 from pgroen/feat/pgroen/modbus-rtu-implementation

Feat/pgroen/modbus rtu implementation
CMakeLists.txt
... ... @@ -8,4 +8,6 @@ include(projectheader)
8 8 project_header(modbus-cpp)
9 9  
10 10 add_subdirectory(src)
  11 +add_subdirectory(tests)
  12 +# add_subdirectory(tools)
11 13  
... ...
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
... ... @@ -57,8 +57,8 @@ namespace modbus {
57 57 class ModbusBase
58 58 {
59 59 public:
60   - ModbusBase();
61   - virtual ~ModbusBase();
  60 + ModbusBase() {}
  61 + virtual ~ModbusBase() {}
62 62  
63 63 // Pure virtuals. Override when inherited.
64 64 virtual bool Connect() = 0;
... ...
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 +
... ...