Commit c8f002d0934e09c35b0387fd4549ba6ab804fc43

Authored by Peter M. Groen
1 parent 2b637911

Add TCP connection

src/CMakeLists.txt
... ... @@ -11,7 +11,6 @@ include_directories(
11 11 )
12 12  
13 13 set(SRC_LIST
14   - ${CMAKE_CURRENT_SOURCE_DIR}/imodbusport.h
15 14 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.h
16 15 ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.cpp
17 16 ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.h
... ...
src/connectionconfig.h
... ... @@ -47,11 +47,28 @@ public:
47 47 // Getters and Setters
48 48 void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; }
49 49 E_CONNECTIONTYPE getConnectionType() const { return m_conType; }
  50 +
50 51 void setBaudRate( E_BAUDRATE baud_rate ) { m_baudRate = baud_rate; }
51 52 E_BAUDRATE getBaudRate() const { return m_baudRate; }
  53 +
52 54 void setParity(E_PARITY parity) { m_parity = parity; }
53 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 72 private:
56 73 E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN;
57 74 E_BAUDRATE m_baudRate = E_BAUDRATE::R9600;
... ... @@ -59,7 +76,7 @@ private:
59 76 int m_dataBits = 8;
60 77 int m_stopBits = 1;
61 78 std::string m_ipAddress{};
62   - unsigned int m_portNUmber = 502;
  79 + unsigned int m_portNumber = 502;
63 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 2 * Copyright (c) 2022 Peter M. Groen
3   - *
  3 + *
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 */
... ... @@ -20,6 +20,10 @@
20 20 #define LOG(...) (void)0
21 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 27 // Function Codes
24 28 #define READ_COILS 0x01
25 29 #define READ_INPUT_BITS 0x02
... ... @@ -74,11 +78,11 @@ public:
74 78 * \return
75 79 */
76 80 virtual int modbusReceive(uint8_t *buffer) = 0;
77   -
  81 +
78 82 // Modbus implementation(s)
79 83 /*!
80   - * Read Coils
81   - * MODBUS Function 0x01
  84 + * Read Coils
  85 + * MODBUS Function 0x01
82 86 * \param address - Reference Address
83 87 * \param amount - Amount of Coils to Read
84 88 * \param buffer - Buffer to Store Data Read from Coils
... ... @@ -86,8 +90,8 @@ public:
86 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 95 * \param address - Refernce Address
92 96 * \param amount - Amount of BITS to Read
93 97 * \param buffer - Buffer to store Data Read from Input Bits
... ... @@ -95,8 +99,8 @@ public:
95 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 104 * \param address - Reference Address
101 105 * \param amount - Amount of Registers to Read
102 106 * \param buffer - Buffer to Store Data Read from Registers
... ... @@ -104,8 +108,8 @@ public:
104 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 113 * \param address - Reference Address
110 114 * \param amount - Amount of registers to read
111 115 * \param buffer - Buffer to store Data Read from Registers
... ... @@ -113,8 +117,8 @@ public:
113 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 122 * \param address - Reference Address
119 123 * \param to_write - Value to be written to Coil
120 124 */
... ... @@ -129,8 +133,8 @@ public:
129 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 138 * \param address - Reference Address
135 139 * \param amount - Amount of coils to write
136 140 * \param value - Values to Be Written to Coils
... ... @@ -138,8 +142,8 @@ public:
138 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 147 * \param address - Reference Address
144 148 * \param amount - Amount of Value to Write
145 149 * \param value - Values to Be Written to the Registers
... ... @@ -182,7 +186,7 @@ private: // Methods
182 186 * \param amount - Amount of data to be written
183 187 * \param function_code - Modbus Functional Code
184 188 * \param value - Data to be written
185   - *
  189 + *
186 190 * \return int -
187 191 */
188 192 int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value);
... ...
src/modbustcp.cpp
... ... @@ -9,27 +9,75 @@
9 9 using namespace osdev::components::modbus;
10 10  
11 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 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 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 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 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 22 using SOCKADDR = struct sockaddr;
23 23 using SOCKADDR_IN = struct sockaddr_in;
24 24  
  25 +#define MAX_MSG_LENGTH 260
  26 +
25 27 class ModbusTcp : public ModbusBase
26 28 {
27 29 public:
... ... @@ -47,8 +49,8 @@ public:
47 49 virtual int modbusReceive(uint8_t *buffer) override;
48 50  
49 51 private:
50   - uint16_t m_port {502};
51 52 std::string m_host {};
  53 + uint16_t m_port {502};
52 54 X_SOCKET m_socket {-1};
53 55 SOCKADDR_IN m_server {};
54 56  
... ...