Commit c8f002d0934e09c35b0387fd4549ba6ab804fc43
1 parent
2b637911
Add TCP connection
Showing
6 changed files
with
94 additions
and
55 deletions
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 |