Commit c8f002d0934e09c35b0387fd4549ba6ab804fc43

Authored by Peter M. Groen
1 parent 2b637911

Add TCP connection

src/CMakeLists.txt
@@ -11,7 +11,6 @@ include_directories( @@ -11,7 +11,6 @@ include_directories(
11 ) 11 )
12 12
13 set(SRC_LIST 13 set(SRC_LIST
14 - ${CMAKE_CURRENT_SOURCE_DIR}/imodbusport.h  
15 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.h 14 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.h
16 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.cpp 15 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.cpp
17 ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.h 16 ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.h
src/connectionconfig.h
@@ -47,11 +47,28 @@ public: @@ -47,11 +47,28 @@ public:
47 // Getters and Setters 47 // Getters and Setters
48 void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; } 48 void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; }
49 E_CONNECTIONTYPE getConnectionType() const { return m_conType; } 49 E_CONNECTIONTYPE getConnectionType() const { return m_conType; }
  50 +
50 void setBaudRate( E_BAUDRATE baud_rate ) { m_baudRate = baud_rate; } 51 void setBaudRate( E_BAUDRATE baud_rate ) { m_baudRate = baud_rate; }
51 E_BAUDRATE getBaudRate() const { return m_baudRate; } 52 E_BAUDRATE getBaudRate() const { return m_baudRate; }
  53 +
52 void setParity(E_PARITY parity) { m_parity = parity; } 54 void setParity(E_PARITY parity) { m_parity = parity; }
53 E_PARITY getParity() const { return m_parity; } 55 E_PARITY getParity() const { return m_parity; }
54 56
  57 + void setDataBits(int data_bits) { m_dataBits = data_bits; }
  58 + int getDataBits() const { return m_dataBits; }
  59 +
  60 + void setStopBits(int stop_bits) { m_stopBits = stop_bits; }
  61 + int getStopBits() const { return m_stopBits; }
  62 +
  63 + void setIpAddress(const std::string &ip_address) { m_ipAddress = ip_address; }
  64 + std::string getIpAddress() const { return m_ipAddress; }
  65 +
  66 + void setPortNumber(unsigned int port_number) { m_portNumber = port_number; }
  67 + unsigned int getPortNumber() const { return m_portNumber; }
  68 +
  69 + void setFrameTimeout(int frame_timeout) { m_frameTimeOut = frame_timeout; }
  70 + int getFrameTimeout() const { return m_frameTimeOut; }
  71 +
55 private: 72 private:
56 E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN; 73 E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN;
57 E_BAUDRATE m_baudRate = E_BAUDRATE::R9600; 74 E_BAUDRATE m_baudRate = E_BAUDRATE::R9600;
@@ -59,7 +76,7 @@ private: @@ -59,7 +76,7 @@ private:
59 int m_dataBits = 8; 76 int m_dataBits = 8;
60 int m_stopBits = 1; 77 int m_stopBits = 1;
61 std::string m_ipAddress{}; 78 std::string m_ipAddress{};
62 - unsigned int m_portNUmber = 502; 79 + unsigned int m_portNumber = 502;
63 int m_frameTimeOut = -1; 80 int m_frameTimeOut = -1;
64 81
65 }; 82 };
src/imodbusport.h deleted
1 -/*  
2 - * Copyright (c) 2022 Peter M. Groen  
3 - *  
4 - * This source code is licensed under the MIT license found in the  
5 - * LICENSE file in the root directory of this source tree.  
6 - */  
7 -#pragma once  
8 -  
9 -#include "connectionconfig.h"  
10 -#include <vector>  
11 -  
12 -namespace osdev {  
13 -namespace components {  
14 -namespace modbus {  
15 -  
16 -class IModbusPort  
17 -{  
18 -public:  
19 - IModbusPort(const ConnectionConfig &con_config);  
20 - virtual ~IModbusPort() {}  
21 -  
22 - // The standard device interface.  
23 - virtual bool Open() const = 0;  
24 - virtual bool Close() const = 0;  
25 - virtual int Read(uint8_t *buffer) const = 0;  
26 - virtual int Write(uint8_t *buffer, size_t length) const = 0;  
27 -};  
28 -  
29 -} /* End namespace modbus */  
30 -} /* End namespace components */  
31 -} /* End namespace osdev */  
src/modbusbase.h
1 /* 1 /*
2 * Copyright (c) 2022 Peter M. Groen 2 * Copyright (c) 2022 Peter M. Groen
3 - * 3 + *
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 */
@@ -20,6 +20,10 @@ @@ -20,6 +20,10 @@
20 #define LOG(...) (void)0 20 #define LOG(...) (void)0
21 #endif 21 #endif
22 22
  23 +#define X_ISVALIDSOCKET(s) ((s) >= 0)
  24 +#define X_CLOSE_SOCKET(s) close(s)
  25 +#define X_ISCONNECTSUCCEED(s) ((s) >= 0)
  26 +
23 // Function Codes 27 // Function Codes
24 #define READ_COILS 0x01 28 #define READ_COILS 0x01
25 #define READ_INPUT_BITS 0x02 29 #define READ_INPUT_BITS 0x02
@@ -74,11 +78,11 @@ public: @@ -74,11 +78,11 @@ public:
74 * \return 78 * \return
75 */ 79 */
76 virtual int modbusReceive(uint8_t *buffer) = 0; 80 virtual int modbusReceive(uint8_t *buffer) = 0;
77 - 81 +
78 // Modbus implementation(s) 82 // Modbus implementation(s)
79 /*! 83 /*!
80 - * Read Coils  
81 - * MODBUS Function 0x01 84 + * Read Coils
  85 + * MODBUS Function 0x01
82 * \param address - Reference Address 86 * \param address - Reference Address
83 * \param amount - Amount of Coils to Read 87 * \param amount - Amount of Coils to Read
84 * \param buffer - Buffer to Store Data Read from Coils 88 * \param buffer - Buffer to Store Data Read from Coils
@@ -86,8 +90,8 @@ public: @@ -86,8 +90,8 @@ public:
86 int readCoils(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible? 90 int readCoils(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible?
87 91
88 /*! 92 /*!
89 - * Read Input Bits  
90 - * MODBUS Function 0x02 93 + * Read Input Bits
  94 + * MODBUS Function 0x02
91 * \param address - Refernce Address 95 * \param address - Refernce Address
92 * \param amount - Amount of BITS to Read 96 * \param amount - Amount of BITS to Read
93 * \param buffer - Buffer to store Data Read from Input Bits 97 * \param buffer - Buffer to store Data Read from Input Bits
@@ -95,8 +99,8 @@ public: @@ -95,8 +99,8 @@ public:
95 int readInputBits(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible? 99 int readInputBits(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible?
96 100
97 /*! 101 /*!
98 - * Read Holding Registers  
99 - * MODBUS Function 0x03 102 + * Read Holding Registers
  103 + * MODBUS Function 0x03
100 * \param address - Reference Address 104 * \param address - Reference Address
101 * \param amount - Amount of Registers to Read 105 * \param amount - Amount of Registers to Read
102 * \param buffer - Buffer to Store Data Read from Registers 106 * \param buffer - Buffer to Store Data Read from Registers
@@ -104,8 +108,8 @@ public: @@ -104,8 +108,8 @@ public:
104 int readHoldingRegisters(uint16_t address, uint16_t amount, uint16_t *buffer); 108 int readHoldingRegisters(uint16_t address, uint16_t amount, uint16_t *buffer);
105 109
106 /*! 110 /*!
107 - * Read Input Registers  
108 - * MODBUS Function 0x04 111 + * Read Input Registers
  112 + * MODBUS Function 0x04
109 * \param address - Reference Address 113 * \param address - Reference Address
110 * \param amount - Amount of registers to read 114 * \param amount - Amount of registers to read
111 * \param buffer - Buffer to store Data Read from Registers 115 * \param buffer - Buffer to store Data Read from Registers
@@ -113,8 +117,8 @@ public: @@ -113,8 +117,8 @@ public:
113 int readInputRegisters(uint16_t address, uint16_t amount, uint16_t *buffer); 117 int readInputRegisters(uint16_t address, uint16_t amount, uint16_t *buffer);
114 118
115 /*! 119 /*!
116 - * Write Single Coils  
117 - * MODBUS Function 0x05 120 + * Write Single Coils
  121 + * MODBUS Function 0x05
118 * \param address - Reference Address 122 * \param address - Reference Address
119 * \param to_write - Value to be written to Coil 123 * \param to_write - Value to be written to Coil
120 */ 124 */
@@ -129,8 +133,8 @@ public: @@ -129,8 +133,8 @@ public:
129 int writeRegister(uint16_t address, const uint16_t &value); 133 int writeRegister(uint16_t address, const uint16_t &value);
130 134
131 /*! 135 /*!
132 - * Write Multiple Coils  
133 - * MODBUS Function 0x0F 136 + * Write Multiple Coils
  137 + * MODBUS Function 0x0F
134 * \param address - Reference Address 138 * \param address - Reference Address
135 * \param amount - Amount of coils to write 139 * \param amount - Amount of coils to write
136 * \param value - Values to Be Written to Coils 140 * \param value - Values to Be Written to Coils
@@ -138,8 +142,8 @@ public: @@ -138,8 +142,8 @@ public:
138 int writeCoils(uint16_t address, uint16_t amount, const bool *value); 142 int writeCoils(uint16_t address, uint16_t amount, const bool *value);
139 143
140 /*! 144 /*!
141 - * Write Multiple Registers  
142 - * MODBUS Function 0x10 145 + * Write Multiple Registers
  146 + * MODBUS Function 0x10
143 * \param address - Reference Address 147 * \param address - Reference Address
144 * \param amount - Amount of Value to Write 148 * \param amount - Amount of Value to Write
145 * \param value - Values to Be Written to the Registers 149 * \param value - Values to Be Written to the Registers
@@ -182,7 +186,7 @@ private: // Methods @@ -182,7 +186,7 @@ private: // Methods
182 * \param amount - Amount of data to be written 186 * \param amount - Amount of data to be written
183 * \param function_code - Modbus Functional Code 187 * \param function_code - Modbus Functional Code
184 * \param value - Data to be written 188 * \param value - Data to be written
185 - * 189 + *
186 * \return int - 190 * \return int -
187 */ 191 */
188 int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value); 192 int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value);
src/modbustcp.cpp
@@ -9,27 +9,75 @@ @@ -9,27 +9,75 @@
9 using namespace osdev::components::modbus; 9 using namespace osdev::components::modbus;
10 10
11 ModbusTcp::ModbusTcp(const ConnectionConfig &con_config) 11 ModbusTcp::ModbusTcp(const ConnectionConfig &con_config)
12 - 12 + : m_host( con_config.getIpAddress() )
  13 + , m_port( con_config.getPortNumber() )
13 { 14 {
14 15
15 } 16 }
16 17
17 bool ModbusTcp::Connect() 18 bool ModbusTcp::Connect()
18 { 19 {
  20 + if (m_host.empty() || m_port == 0)
  21 + {
  22 + LOG("Missing Host and Port");
  23 + return false;
  24 + }
  25 + else
  26 + {
  27 + LOG("Found Proper Host %s and Port %d", m_host.c_str(), m_port);
  28 + }
  29 +
  30 + m_socket = socket(AF_INET, SOCK_STREAM, 0);
  31 + if (!X_ISVALIDSOCKET(m_socket))
  32 + {
  33 + LOG("Error Opening Socket");
  34 + return false;
  35 + }
  36 + else
  37 + {
  38 + LOG("Socket Opened Successfully");
  39 + }
  40 +
  41 + struct timeval timeout
  42 + {
  43 + };
  44 + timeout.tv_sec = 20; // after 20 seconds connect() will timeout
  45 + timeout.tv_usec = 0;
  46 +
19 47
  48 + setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<const char *>(&timeout), sizeof(timeout));
  49 + setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char *>(&timeout), sizeof(timeout));
  50 + m_server.sin_family = AF_INET;
  51 + m_server.sin_addr.s_addr = inet_addr(m_host.c_str());
  52 + m_server.sin_port = htons(m_port);
  53 +
  54 + if (!X_ISCONNECTSUCCEED(connect(m_socket, reinterpret_cast<SOCKADDR *>(&m_server), sizeof(m_server))))
  55 + {
  56 + LOG("Connection Error");
  57 + return false;
  58 + }
  59 +
  60 + LOG("Connected");
  61 + ModbusBase::setConnected( true );
  62 + return true;
20 } 63 }
21 64
22 bool ModbusTcp::Close() 65 bool ModbusTcp::Close()
23 { 66 {
24 - 67 + X_CLOSE_SOCKET(m_socket);
  68 + LOG("Socket Closed");
  69 + ModbusBase::setConnected(false);
  70 + return ModbusBase::getConnected();
25 } 71 }
26 72
27 int ModbusTcp::modbusReceive(uint8_t *buffer) 73 int ModbusTcp::modbusReceive(uint8_t *buffer)
28 { 74 {
29 - return 0; 75 + return recv(m_socket, reinterpret_cast<char *>(buffer), MAX_MSG_LENGTH, 0);
30 } 76 }
31 77
32 int ModbusTcp::modbusSend(uint8_t *buffer, size_t length) 78 int ModbusTcp::modbusSend(uint8_t *buffer, size_t length)
33 { 79 {
34 - return 0; 80 + uint32_t msg_id = ModbusBase::getMessageId();
  81 + ModbusBase::setMessageId(msg_id++);
  82 + return send(m_socket, reinterpret_cast<const char *>(buffer), static_cast<size_t>(length), 0);
35 } 83 }
src/modbustcp.h
@@ -22,6 +22,8 @@ using X_SOCKET = int; @@ -22,6 +22,8 @@ using X_SOCKET = int;
22 using SOCKADDR = struct sockaddr; 22 using SOCKADDR = struct sockaddr;
23 using SOCKADDR_IN = struct sockaddr_in; 23 using SOCKADDR_IN = struct sockaddr_in;
24 24
  25 +#define MAX_MSG_LENGTH 260
  26 +
25 class ModbusTcp : public ModbusBase 27 class ModbusTcp : public ModbusBase
26 { 28 {
27 public: 29 public:
@@ -47,8 +49,8 @@ public: @@ -47,8 +49,8 @@ public:
47 virtual int modbusReceive(uint8_t *buffer) override; 49 virtual int modbusReceive(uint8_t *buffer) override;
48 50
49 private: 51 private:
50 - uint16_t m_port {502};  
51 std::string m_host {}; 52 std::string m_host {};
  53 + uint16_t m_port {502};
52 X_SOCKET m_socket {-1}; 54 X_SOCKET m_socket {-1};
53 SOCKADDR_IN m_server {}; 55 SOCKADDR_IN m_server {};
54 56