From c8f002d0934e09c35b0387fd4549ba6ab804fc43 Mon Sep 17 00:00:00 2001 From: Peter M. Groen Date: Tue, 13 Dec 2022 23:17:33 +0100 Subject: [PATCH] Add TCP connection --- src/CMakeLists.txt | 1 - src/connectionconfig.h | 19 ++++++++++++++++++- src/imodbusport.h | 31 ------------------------------- src/modbusbase.h | 38 +++++++++++++++++++++----------------- src/modbustcp.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/modbustcp.h | 4 +++- 6 files changed, 94 insertions(+), 55 deletions(-) delete mode 100644 src/imodbusport.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebfcf34..6fbcada 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,6 @@ include_directories( ) set(SRC_LIST - ${CMAKE_CURRENT_SOURCE_DIR}/imodbusport.h ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.h ${CMAKE_CURRENT_SOURCE_DIR}/modbusbase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/modbustcp.h diff --git a/src/connectionconfig.h b/src/connectionconfig.h index 8f62074..d9bc7df 100644 --- a/src/connectionconfig.h +++ b/src/connectionconfig.h @@ -47,11 +47,28 @@ public: // Getters and Setters void setConnectionType( E_CONNECTIONTYPE type ) { m_conType = type; } E_CONNECTIONTYPE getConnectionType() const { return m_conType; } + void setBaudRate( E_BAUDRATE baud_rate ) { m_baudRate = baud_rate; } E_BAUDRATE getBaudRate() const { return m_baudRate; } + void setParity(E_PARITY parity) { m_parity = parity; } E_PARITY getParity() const { return m_parity; } + void setDataBits(int data_bits) { m_dataBits = data_bits; } + int getDataBits() const { return m_dataBits; } + + void setStopBits(int stop_bits) { m_stopBits = stop_bits; } + int getStopBits() const { return m_stopBits; } + + void setIpAddress(const std::string &ip_address) { m_ipAddress = ip_address; } + std::string getIpAddress() const { return m_ipAddress; } + + void setPortNumber(unsigned int port_number) { m_portNumber = port_number; } + unsigned int getPortNumber() const { return m_portNumber; } + + void setFrameTimeout(int frame_timeout) { m_frameTimeOut = frame_timeout; } + int getFrameTimeout() const { return m_frameTimeOut; } + private: E_CONNECTIONTYPE m_conType = E_CONNECTIONTYPE::UNKNOWN; E_BAUDRATE m_baudRate = E_BAUDRATE::R9600; @@ -59,7 +76,7 @@ private: int m_dataBits = 8; int m_stopBits = 1; std::string m_ipAddress{}; - unsigned int m_portNUmber = 502; + unsigned int m_portNumber = 502; int m_frameTimeOut = -1; }; diff --git a/src/imodbusport.h b/src/imodbusport.h deleted file mode 100644 index b54f8e4..0000000 --- a/src/imodbusport.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2022 Peter M. Groen - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -#pragma once - -#include "connectionconfig.h" -#include - -namespace osdev { -namespace components { -namespace modbus { - -class IModbusPort -{ -public: - IModbusPort(const ConnectionConfig &con_config); - virtual ~IModbusPort() {} - - // The standard device interface. - virtual bool Open() const = 0; - virtual bool Close() const = 0; - virtual int Read(uint8_t *buffer) const = 0; - virtual int Write(uint8_t *buffer, size_t length) const = 0; -}; - -} /* End namespace modbus */ -} /* End namespace components */ -} /* End namespace osdev */ diff --git a/src/modbusbase.h b/src/modbusbase.h index 6ae0505..378cf82 100644 --- a/src/modbusbase.h +++ b/src/modbusbase.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2022 Peter M. Groen - * + * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ @@ -20,6 +20,10 @@ #define LOG(...) (void)0 #endif +#define X_ISVALIDSOCKET(s) ((s) >= 0) +#define X_CLOSE_SOCKET(s) close(s) +#define X_ISCONNECTSUCCEED(s) ((s) >= 0) + // Function Codes #define READ_COILS 0x01 #define READ_INPUT_BITS 0x02 @@ -74,11 +78,11 @@ public: * \return */ virtual int modbusReceive(uint8_t *buffer) = 0; - + // Modbus implementation(s) /*! - * Read Coils - * MODBUS Function 0x01 + * Read Coils + * MODBUS Function 0x01 * \param address - Reference Address * \param amount - Amount of Coils to Read * \param buffer - Buffer to Store Data Read from Coils @@ -86,8 +90,8 @@ public: int readCoils(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible? /*! - * Read Input Bits - * MODBUS Function 0x02 + * Read Input Bits + * MODBUS Function 0x02 * \param address - Refernce Address * \param amount - Amount of BITS to Read * \param buffer - Buffer to store Data Read from Input Bits @@ -95,8 +99,8 @@ public: int readInputBits(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible? /*! - * Read Holding Registers - * MODBUS Function 0x03 + * Read Holding Registers + * MODBUS Function 0x03 * \param address - Reference Address * \param amount - Amount of Registers to Read * \param buffer - Buffer to Store Data Read from Registers @@ -104,8 +108,8 @@ public: int readHoldingRegisters(uint16_t address, uint16_t amount, uint16_t *buffer); /*! - * Read Input Registers - * MODBUS Function 0x04 + * Read Input Registers + * MODBUS Function 0x04 * \param address - Reference Address * \param amount - Amount of registers to read * \param buffer - Buffer to store Data Read from Registers @@ -113,8 +117,8 @@ public: int readInputRegisters(uint16_t address, uint16_t amount, uint16_t *buffer); /*! - * Write Single Coils - * MODBUS Function 0x05 + * Write Single Coils + * MODBUS Function 0x05 * \param address - Reference Address * \param to_write - Value to be written to Coil */ @@ -129,8 +133,8 @@ public: int writeRegister(uint16_t address, const uint16_t &value); /*! - * Write Multiple Coils - * MODBUS Function 0x0F + * Write Multiple Coils + * MODBUS Function 0x0F * \param address - Reference Address * \param amount - Amount of coils to write * \param value - Values to Be Written to Coils @@ -138,8 +142,8 @@ public: int writeCoils(uint16_t address, uint16_t amount, const bool *value); /*! - * Write Multiple Registers - * MODBUS Function 0x10 + * Write Multiple Registers + * MODBUS Function 0x10 * \param address - Reference Address * \param amount - Amount of Value to Write * \param value - Values to Be Written to the Registers @@ -182,7 +186,7 @@ private: // Methods * \param amount - Amount of data to be written * \param function_code - Modbus Functional Code * \param value - Data to be written - * + * * \return int - */ int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value); diff --git a/src/modbustcp.cpp b/src/modbustcp.cpp index 4589f62..7f95187 100644 --- a/src/modbustcp.cpp +++ b/src/modbustcp.cpp @@ -9,27 +9,75 @@ using namespace osdev::components::modbus; ModbusTcp::ModbusTcp(const ConnectionConfig &con_config) - + : m_host( con_config.getIpAddress() ) + , m_port( con_config.getPortNumber() ) { } bool ModbusTcp::Connect() { + if (m_host.empty() || m_port == 0) + { + LOG("Missing Host and Port"); + return false; + } + else + { + LOG("Found Proper Host %s and Port %d", m_host.c_str(), m_port); + } + + m_socket = socket(AF_INET, SOCK_STREAM, 0); + if (!X_ISVALIDSOCKET(m_socket)) + { + LOG("Error Opening Socket"); + return false; + } + else + { + LOG("Socket Opened Successfully"); + } + + struct timeval timeout + { + }; + timeout.tv_sec = 20; // after 20 seconds connect() will timeout + timeout.tv_usec = 0; + + setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&timeout), sizeof(timeout)); + setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeout), sizeof(timeout)); + m_server.sin_family = AF_INET; + m_server.sin_addr.s_addr = inet_addr(m_host.c_str()); + m_server.sin_port = htons(m_port); + + if (!X_ISCONNECTSUCCEED(connect(m_socket, reinterpret_cast(&m_server), sizeof(m_server)))) + { + LOG("Connection Error"); + return false; + } + + LOG("Connected"); + ModbusBase::setConnected( true ); + return true; } bool ModbusTcp::Close() { - + X_CLOSE_SOCKET(m_socket); + LOG("Socket Closed"); + ModbusBase::setConnected(false); + return ModbusBase::getConnected(); } int ModbusTcp::modbusReceive(uint8_t *buffer) { - return 0; + return recv(m_socket, reinterpret_cast(buffer), MAX_MSG_LENGTH, 0); } int ModbusTcp::modbusSend(uint8_t *buffer, size_t length) { - return 0; + uint32_t msg_id = ModbusBase::getMessageId(); + ModbusBase::setMessageId(msg_id++); + return send(m_socket, reinterpret_cast(buffer), static_cast(length), 0); } diff --git a/src/modbustcp.h b/src/modbustcp.h index a2725cd..1d2e851 100644 --- a/src/modbustcp.h +++ b/src/modbustcp.h @@ -22,6 +22,8 @@ using X_SOCKET = int; using SOCKADDR = struct sockaddr; using SOCKADDR_IN = struct sockaddr_in; +#define MAX_MSG_LENGTH 260 + class ModbusTcp : public ModbusBase { public: @@ -47,8 +49,8 @@ public: virtual int modbusReceive(uint8_t *buffer) override; private: - uint16_t m_port {502}; std::string m_host {}; + uint16_t m_port {502}; X_SOCKET m_socket {-1}; SOCKADDR_IN m_server {}; -- libgit2 0.21.4