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