diff --git a/.gitignore b/.gitignore index f928faf..35dbc63 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,8 @@ *.app build +out +.vs # Gtags GTAGS diff --git a/CMakeLists.txt b/CMakeLists.txt index ea0338a..6b2233c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ -cmake_minimum_required(VERSION 3.13) -project(protocolConverter) +project(modbus) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) if (DCMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -lpthread -Wall") @@ -9,7 +8,8 @@ endif() option(MODBUS_EXAMPLE "Build example program" OFF) option(MODBUS_TESTS "Build tests" OFF) -option(MODBUS_COMMUNICATION "Use Modbus communication library" ON) +option(MODBUS_TCP_COMMUNICATION "Use Modbus TCP communication library" ON) +option(MODBUS_SERIAL_COMMUNICATION "Use Modbus serial communication library" OFF) # not supported by windows platform add_subdirectory(src) @@ -21,4 +21,3 @@ if(MODBUS_EXAMPLE) add_executable(ex example/main.cpp) target_link_libraries(ex Modbus) endif() - diff --git a/include/MB/Serial/connection.hpp b/include/MB/Serial/connection.hpp index 772229a..cb4af79 100644 --- a/include/MB/Serial/connection.hpp +++ b/include/MB/Serial/connection.hpp @@ -1,127 +1,127 @@ -// Modbus for c++ -// Copyright (c) 2020 Mateusz Mazur aka Mazurel -// Licensed under: MIT License - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "MB/modbusException.hpp" -#include "MB/modbusRequest.hpp" -#include "MB/modbusResponse.hpp" -#include "MB/modbusUtils.hpp" - -namespace MB::Serial { -class Connection { -public: - // Pretty high timeout - static const unsigned int DefaultSerialTimeout = 100; - -private: - struct termios _termios; - int _fd; - - int _timeout = Connection::DefaultSerialTimeout; - -public: - constexpr explicit Connection() : _termios(), _fd(-1) {} - explicit Connection(const std::string &path); - explicit Connection(const Connection &) = delete; - explicit Connection(Connection &&) noexcept; - Connection &operator=(Connection &&); - ~Connection(); - - void connect(); - - std::vector sendRequest(const MB::ModbusRequest &request); - std::vector sendResponse(const MB::ModbusResponse &response); - std::vector sendException(const MB::ModbusException &exception); - - /** - * @brief Sends data through the serial - * @param data - Vectorized data - */ - std::vector send(std::vector data); - - void clearInput(); - - [[nodiscard]] std::tuple> awaitResponse(); - [[nodiscard]] std::tuple> awaitRequest(); - - [[nodiscard]] std::vector awaitRawMessage(); - - void enableParity(const bool parity) { - if (parity) - getTTY().c_cflag |= PARENB; - else - getTTY().c_cflag &= ~PARENB; - } - - void setEvenParity() { - enableParity(true); - getTTY().c_cflag &= ~PARODD; - } - - void setOddParity() { - enableParity(true); - getTTY().c_cflag |= PARODD; - } - - void setTwoStopBits(const bool two) { - if (two) { - getTTY().c_cflag |= CSTOPB; - } else { - getTTY().c_cflag &= ~CSTOPB; - } - } - -#define setBaud(s) \ - case s: \ - speed = B##s; \ - break; - void setBaudRate(speed_t speed) { - switch (speed) { - setBaud(0); - setBaud(50); - setBaud(75); - setBaud(110); - setBaud(134); - setBaud(150); - setBaud(200); - setBaud(300); - setBaud(600); - setBaud(1200); - setBaud(1800); - setBaud(2400); - setBaud(4800); - setBaud(9600); - setBaud(19200); - setBaud(38400); - setBaud(57600); - setBaud(115200); - setBaud(230400); - default: - throw std::runtime_error("Invalid baud rate"); - } - cfsetospeed(&_termios, speed); - cfsetispeed(&_termios, speed); - } -#undef setBaud - - termios &getTTY() { return _termios; } - - int getTimeout() const { return _timeout; } - - void setTimeout(int timeout) { _timeout = timeout; } -}; -} // namespace MB::Serial +// Modbus for c++ +// Copyright (c) 2020 Mateusz Mazur aka Mazurel +// Licensed under: MIT License + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "MB/modbusException.hpp" +#include "MB/modbusRequest.hpp" +#include "MB/modbusResponse.hpp" +#include "MB/modbusUtils.hpp" + +namespace MB::Serial { +class Connection { +public: + // Pretty high timeout + static const unsigned int DefaultSerialTimeout = 100; + +private: + struct termios _termios; + int _fd; + + int _timeout = Connection::DefaultSerialTimeout; + +public: + constexpr explicit Connection() : _termios(), _fd(-1) {} + explicit Connection(const std::string &path); + explicit Connection(const Connection &) = delete; + explicit Connection(Connection &&) noexcept; + Connection &operator=(Connection &&); + ~Connection(); + + void connect(); + + std::vector sendRequest(const MB::ModbusRequest &request); + std::vector sendResponse(const MB::ModbusResponse &response); + std::vector sendException(const MB::ModbusException &exception); + + /** + * @brief Sends data through the serial + * @param data - Vectorized data + */ + std::vector send(std::vector data); + + void clearInput(); + + [[nodiscard]] std::tuple> awaitResponse(); + [[nodiscard]] std::tuple> awaitRequest(); + + [[nodiscard]] std::vector awaitRawMessage(); + + void enableParity(const bool parity) { + if (parity) + getTTY().c_cflag |= PARENB; + else + getTTY().c_cflag &= ~PARENB; + } + + void setEvenParity() { + enableParity(true); + getTTY().c_cflag &= ~PARODD; + } + + void setOddParity() { + enableParity(true); + getTTY().c_cflag |= PARODD; + } + + void setTwoStopBits(const bool two) { + if (two) { + getTTY().c_cflag |= CSTOPB; + } else { + getTTY().c_cflag &= ~CSTOPB; + } + } + +#define setBaud(s) \ + case s: \ + speed = B##s; \ + break; + void setBaudRate(speed_t speed) { + switch (speed) { + setBaud(0); + setBaud(50); + setBaud(75); + setBaud(110); + setBaud(134); + setBaud(150); + setBaud(200); + setBaud(300); + setBaud(600); + setBaud(1200); + setBaud(1800); + setBaud(2400); + setBaud(4800); + setBaud(9600); + setBaud(19200); + setBaud(38400); + setBaud(57600); + setBaud(115200); + setBaud(230400); + default: + throw std::runtime_error("Invalid baud rate"); + } + cfsetospeed(&_termios, speed); + cfsetispeed(&_termios, speed); + } +#undef setBaud + + termios &getTTY() { return _termios; } + + int getTimeout() const { return _timeout; } + + void setTimeout(int timeout) { _timeout = timeout; } +}; +} // namespace MB::Serial diff --git a/include/MB/TCP/connection.hpp b/include/MB/TCP/connection.hpp index cfadf60..ed80e46 100644 --- a/include/MB/TCP/connection.hpp +++ b/include/MB/TCP/connection.hpp @@ -4,20 +4,16 @@ #pragma once -#include -#include +#include +#include -#include -#include -#include -#include -#include +#include "../modbusException.hpp" +#include "../modbusRequest.hpp" +#include "../modbusResponse.hpp" -#include "MB/modbusException.hpp" -#include "MB/modbusRequest.hpp" -#include "MB/modbusResponse.hpp" +namespace MB { +namespace TCP { -namespace MB::TCP { class Connection { public: static const unsigned int DefaultTCPTimeout = 500; @@ -27,28 +23,18 @@ class Connection { uint16_t _messageID = 0; int _timeout = Connection::DefaultTCPTimeout; + void closeSockfd(void); + public: explicit Connection() noexcept : _sockfd(-1), _messageID(0){}; explicit Connection(int sockfd) noexcept; Connection(const Connection ©) = delete; Connection(Connection &&moved) noexcept; - Connection &operator=(Connection &&other) noexcept { - if (this == &other) - return *this; - - if (_sockfd != -1 && _sockfd != other._sockfd) - ::close(_sockfd); - - _sockfd = other._sockfd; - _messageID = other._messageID; - other._sockfd = -1; - - return *this; - } + Connection& operator=(Connection&& other) noexcept; [[nodiscard]] int getSockfd() const { return _sockfd; } - static Connection with(std::string addr, int port); + static Connection with(const std::string &addr, int port); ~Connection(); @@ -65,4 +51,4 @@ class Connection { void setMessageId(uint16_t messageId) { _messageID = messageId; } }; -} // namespace MB::TCP +}} // namespace MB::TCP diff --git a/include/MB/TCP/server.hpp b/include/MB/TCP/server.hpp index 20eb6d4..daa5379 100644 --- a/include/MB/TCP/server.hpp +++ b/include/MB/TCP/server.hpp @@ -4,17 +4,20 @@ #pragma once -#include -#include -#include - +#ifdef _WIN32 +#include +#include +#else #include #include #include +#endif #include "connection.hpp" -namespace MB::TCP { +namespace MB { +namespace TCP { + class Server { private: int _serverfd; @@ -26,23 +29,25 @@ class Server { ~Server(); Server(const Server &) = delete; - Server(Server &&moved) { + Server(Server &&moved) noexcept { _serverfd = moved._serverfd; _port = moved._port; + _server = moved._server; moved._serverfd = -1; } - Server &operator=(Server &&moved) { + Server &operator=(Server &&moved) noexcept { if (this == &moved) return *this; _serverfd = moved._serverfd; _port = moved._port; + _server = moved._server; moved._serverfd = -1; return *this; } - [[nodiscard]] int nativeHandle() { return _serverfd; } + [[nodiscard]] int nativeHandle() const { return _serverfd; } - std::optional awaitConnection(); + Connection awaitConnection(); }; -} // namespace MB::TCP +}} // namespace MB::TCP diff --git a/include/MB/modbusCell.hpp b/include/MB/modbusCell.hpp index 5d61323..0266658 100644 --- a/include/MB/modbusCell.hpp +++ b/include/MB/modbusCell.hpp @@ -7,6 +7,7 @@ #include #include #include +#include /** * Namespace that contains whole project @@ -18,7 +19,7 @@ namespace MB { */ class ModbusCell { private: - std::variant _value; + std::variant _value; public: /** diff --git a/include/MB/modbusException.hpp b/include/MB/modbusException.hpp index 6ee6d61..9f811d1 100644 --- a/include/MB/modbusException.hpp +++ b/include/MB/modbusException.hpp @@ -85,7 +85,11 @@ class ModbusException : public std::exception { [[nodiscard]] const char *what() const noexcept override { auto og = toString(); char *str = new char[og.size()]; +#ifdef _WIN32 + strncpy_s(str, og.size(), og.c_str(), og.size()); +#else stpcpy(str, og.c_str()); +#endif return str; } diff --git a/include/MB/modbusRequest.hpp b/include/MB/modbusRequest.hpp index aac29e8..d940681 100644 --- a/include/MB/modbusRequest.hpp +++ b/include/MB/modbusRequest.hpp @@ -17,7 +17,7 @@ */ namespace MB { /** - * This class represent Modbus response, it allows + * This class represent Modbus request, it allows * user to manipulate and display it in various ways. */ class ModbusRequest { @@ -69,7 +69,7 @@ class ModbusRequest { } /** - * Simple constructor, that allows to create "dummy" ModbusResponse + * Simple constructor, that allows to create "dummy" ModbusRequest * object. May be useful in some cases. */ explicit ModbusRequest(uint8_t slaveId = 0, diff --git a/include/MB/modbusResponse.hpp b/include/MB/modbusResponse.hpp index 02c04dd..83e9a71 100644 --- a/include/MB/modbusResponse.hpp +++ b/include/MB/modbusResponse.hpp @@ -46,14 +46,14 @@ class ModbusResponse { *exception if it is invalid * @throws ModbusException **/ - explicit ModbusResponse(std::vector inputData, bool CRC = false); + explicit ModbusResponse(const std::vector &inputData, bool CRC = false); /* * @description Constructs Response from raw data * @params inputData is a vector of bytes that will be interpreted * @throws ModbusException **/ - static ModbusResponse fromRaw(std::vector inputData) { + static ModbusResponse fromRaw(const std::vector &inputData) { return ModbusResponse(inputData); } /* @@ -63,7 +63,7 @@ class ModbusResponse { * @note This methods performs CRC check that may throw ModbusException on * invalid CRC **/ - static ModbusResponse fromRawCRC(std::vector inputData) { + static ModbusResponse fromRawCRC(const std::vector &inputData) { return ModbusResponse(inputData, true); } @@ -75,7 +75,7 @@ class ModbusResponse { utils::MBFunctionCode functionCode = static_cast(0), uint16_t address = 0, uint16_t registersNumber = 0, - std::vector values = {}); + const std::vector &values = {}); ModbusResponse(const ModbusResponse &) = default; diff --git a/include/MB/modbusUtils.hpp b/include/MB/modbusUtils.hpp index 62a1f5f..a70de30 100644 --- a/include/MB/modbusUtils.hpp +++ b/include/MB/modbusUtils.hpp @@ -16,7 +16,9 @@ * Namespace that contains many useful utility functions and enums * that are used in the whole project. */ -namespace MB::utils { +namespace MB { +namespace utils { + /*! All possible modbus error codes * @note Contains custom, non standard codes */ @@ -257,7 +259,7 @@ inline uint16_t calculateCRC(const uint8_t *buff, size_t len) { //! Calculate CRC wrapper inline uint16_t calculateCRC(const std::vector &buffer) { - return calculateCRC(buffer.begin().base(), buffer.size()); + return calculateCRC(buffer.data(), buffer.size()); } //! Split uint16_t to two uint8_t in big endian form @@ -275,4 +277,4 @@ inline void pushUint16(std::vector& buffer, const uint16_t val) { buffer.push_back(low); } -} // namespace MB::utils +}} // namespace MB::utils diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56b2940..0a660cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,9 +19,14 @@ add_library(Modbus) target_link_libraries(Modbus Modbus_Core) -if(MODBUS_COMMUNICATION) - message("Modbus communication is experimental") +if(MODBUS_TCP_COMMUNICATION) + message("Modbus TCP communication is experimental") add_subdirectory(TCP) + target_link_libraries(Modbus Modbus_TCP) +endif() + +if(MODBUS_SERIAL_COMMUNICATION) + message("Modbus serial communication is experimental") add_subdirectory(Serial) - target_link_libraries(Modbus Modbus_TCP Modbus_Serial) + target_link_libraries(Modbus Modbus_Serial) endif() diff --git a/src/Serial/connection.cpp b/src/Serial/connection.cpp index c552954..51d1998 100644 --- a/src/Serial/connection.cpp +++ b/src/Serial/connection.cpp @@ -2,6 +2,7 @@ // Copyright (c) 2020 Mateusz Mazur aka Mazurel // Licensed under: MIT License +#ifndef _WIN32 #include "Serial/connection.hpp" using namespace MB::Serial; @@ -152,3 +153,5 @@ Connection &Connection::operator=(Connection &&moved) { moved._fd = -1; return *this; } + +#endif diff --git a/src/TCP/connection.cpp b/src/TCP/connection.cpp index b6feef9..2b444d8 100644 --- a/src/TCP/connection.cpp +++ b/src/TCP/connection.cpp @@ -2,8 +2,23 @@ // Copyright (c) 2020 Mateusz Mazur aka Mazurel // Licensed under: MIT License +#include +#include +#include #include "TCP/connection.hpp" +#ifdef _WIN32 +#include +#include +#define poll(a, b, c) WSAPoll((a), (b), (c)) +#else +#define SOCKET (int) +#include +#include +#include +#include +#endif + using namespace MB::TCP; Connection::Connection(const int sockfd) noexcept { @@ -11,11 +26,33 @@ Connection::Connection(const int sockfd) noexcept { _messageID = 0; } +Connection& Connection::operator=(Connection&& other) noexcept { + if (this == &other) + return *this; + + if (_sockfd != -1 && _sockfd != other._sockfd) { + closeSockfd(); + } + + _sockfd = other._sockfd; + _messageID = other._messageID; + other._sockfd = -1; + + return *this; +} + Connection::~Connection() { - if (_sockfd == -1) - return; + closeSockfd(); +} - ::close(_sockfd); +void Connection::closeSockfd(void) { + if (_sockfd >= 0) { +#ifdef _WIN32 + closesocket(_sockfd); +#else + ::close(_sockfd); +#endif + } _sockfd = -1; } @@ -30,13 +67,13 @@ std::vector Connection::sendRequest(const MB::ModbusRequest &req) { std::vector dat = req.toRaw(); - uint32_t size = dat.size(); - rawReq.push_back(reinterpret_cast(&size)[1]); - rawReq.push_back(reinterpret_cast(&size)[0]); + uint32_t size = (uint32_t)dat.size(); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[1]); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[0]); rawReq.insert(rawReq.end(), dat.begin(), dat.end()); - ::send(_sockfd, rawReq.begin().base(), rawReq.size(), 0); + ::send(_sockfd, (const char*)rawReq.data(), (int)rawReq.size(), 0); return rawReq; } @@ -52,13 +89,13 @@ std::vector Connection::sendResponse(const MB::ModbusResponse &res) { std::vector dat = res.toRaw(); - uint32_t size = dat.size(); - rawReq.push_back(reinterpret_cast(&size)[1]); - rawReq.push_back(reinterpret_cast(&size)[0]); + uint32_t size = (uint32_t)dat.size(); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[1]); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[0]); rawReq.insert(rawReq.end(), dat.begin(), dat.end()); - ::send(_sockfd, rawReq.begin().base(), rawReq.size(), 0); + ::send(_sockfd, (const char*)rawReq.data(), (int)rawReq.size(), 0); return rawReq; } @@ -74,19 +111,19 @@ std::vector Connection::sendException(const MB::ModbusException &ex) { std::vector dat = ex.toRaw(); - uint32_t size = dat.size(); - rawReq.push_back(reinterpret_cast(&size)[1]); - rawReq.push_back(reinterpret_cast(&size)[0]); + uint32_t size = (uint32_t)dat.size(); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[1]); + rawReq.push_back((uint8_t)reinterpret_cast(&size)[0]); rawReq.insert(rawReq.end(), dat.begin(), dat.end()); - ::send(_sockfd, rawReq.begin().base(), rawReq.size(), 0); + ::send(_sockfd, (const char*)rawReq.data(), (int)rawReq.size(), 0); return rawReq; } std::vector Connection::awaitRawMessage() { - pollfd _pfd = {.fd = _sockfd, .events = POLLIN, .revents = POLLIN}; + pollfd _pfd = {.fd = (SOCKET)_sockfd, .events = POLLIN, .revents = POLLIN}; if (::poll(&_pfd, 1, 60 * 1000 /* 1 minute means the connection has died */) <= 0) { throw MB::ModbusException(MB::utils::ConnectionClosed); @@ -94,7 +131,7 @@ std::vector Connection::awaitRawMessage() { std::vector r(1024); - auto size = ::recv(_sockfd, r.begin().base(), r.size(), 0); + auto size = ::recv(_sockfd, (char*)r.data(), (int)r.size(), 0); if (size == -1) throw MB::ModbusException(MB::utils::ProtocolError); @@ -109,7 +146,7 @@ std::vector Connection::awaitRawMessage() { } MB::ModbusRequest Connection::awaitRequest() { - pollfd _pfd = {.fd = _sockfd, .events = POLLIN, .revents = POLLIN}; + pollfd _pfd = {.fd = (SOCKET)_sockfd, .events = POLLIN, .revents = POLLIN}; if (::poll(&_pfd, 1, 60 * 1000 /* 1 minute means the connection has died */) <= 0) { throw MB::ModbusException(MB::utils::Timeout); @@ -117,7 +154,7 @@ MB::ModbusRequest Connection::awaitRequest() { std::vector r(1024); - auto size = ::recv(_sockfd, r.begin().base(), r.size(), 0); + auto size = ::recv(_sockfd, (char*)r.data(), (int)r.size(), 0); if (size == -1) throw MB::ModbusException(MB::utils::ProtocolError); @@ -138,13 +175,13 @@ MB::ModbusRequest Connection::awaitRequest() { } MB::ModbusResponse Connection::awaitResponse() { - pollfd _pfd = {.fd = _sockfd, .events = POLLIN, .revents = POLLIN}; + pollfd _pfd = {.fd = (SOCKET)_sockfd, .events = POLLIN, .revents = POLLIN}; if (::poll(&_pfd, 1, _timeout) <= 0) { throw MB::ModbusException(MB::utils::Timeout); } std::vector r(1024); - auto size = ::recv(_sockfd, r.begin().base(), r.size(), 0); + auto size = ::recv(_sockfd, (char*)r.data(), (int)r.size(), 0); if (size == -1) throw MB::ModbusException(MB::utils::ProtocolError); @@ -169,29 +206,40 @@ MB::ModbusResponse Connection::awaitResponse() { } Connection::Connection(Connection &&moved) noexcept { - if (_sockfd != -1 && moved._sockfd != _sockfd) - ::close(_sockfd); + if (_sockfd != -1 && moved._sockfd != _sockfd) { + closeSockfd(); + } _sockfd = moved._sockfd; _messageID = moved._messageID; moved._sockfd = -1; } -Connection Connection::with(std::string addr, int port) { +Connection Connection::with(const std::string &addr, int port) { +#ifdef _WIN32 + // initialize Windows Socket API with given VERSION. + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { + throw std::runtime_error("WSAStartup failure, errno = " + + std::to_string(errno)); + } +#endif + auto sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) throw std::runtime_error("Cannot open socket, errno = " + std::to_string(errno)); - sockaddr_in server = {.sin_family = AF_INET, - .sin_port = htons(port), - .sin_addr = {inet_addr(addr.c_str())}, - .sin_zero = {}}; + sockaddr_in server = { .sin_family = AF_INET, + .sin_port = htons(port), + .sin_addr = {}, + .sin_zero = {} }; + ::inet_pton(AF_INET, addr.c_str(), &server.sin_addr); if (::connect(sock, reinterpret_cast(&server), sizeof(server)) < 0) throw std::runtime_error("Cannot connect, errno = " + std::to_string(errno)); - return Connection(sock); + return Connection((int)sock); } diff --git a/src/TCP/server.cpp b/src/TCP/server.cpp index a05ce8e..3e5cb89 100644 --- a/src/TCP/server.cpp +++ b/src/TCP/server.cpp @@ -2,22 +2,27 @@ // Copyright (c) 2020 Mateusz Mazur aka Mazurel // Licensed under: MIT License +#include +#include #include "TCP/server.hpp" using namespace MB::TCP; Server::Server(int port) { _port = port; - _serverfd = socket(AF_INET, SOCK_STREAM, 0); + _serverfd = (int)socket(AF_INET, SOCK_STREAM, 0); if (_serverfd == -1) throw std::runtime_error("Cannot create socket"); - setsockopt(_serverfd, SOL_SOCKET, SO_REUSEADDR, new int(1), sizeof(int)); - setsockopt(_serverfd, SOL_SOCKET, SO_REUSEPORT, new int(1), sizeof(int)); + uint32_t reuseaddr = 1; + setsockopt(_serverfd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof(reuseaddr)); +#ifdef SO_REUSEPORT + setsockopt(_serverfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuseaddr, sizeof(reuseaddr)); + (const char*)&reuseaddr +#endif _server = {}; - _server.sin_family = AF_INET; _server.sin_addr.s_addr = INADDR_ANY; _server.sin_port = ::htons(_port); @@ -30,13 +35,18 @@ Server::Server(int port) { } Server::~Server() { - if (_serverfd >= 0) - ::close(_serverfd); + if (_serverfd >= 0) { +#ifdef _WIN32 + closesocket(_serverfd); +#else + ::close(_serverfd); +#endif + } _serverfd = -1; } -std::optional Server::awaitConnection() { +Connection Server::awaitConnection() { socklen_t addrLen = sizeof(_server); auto connfd = ::accept( @@ -45,5 +55,5 @@ std::optional Server::awaitConnection() { if (connfd < 0) throw; - return Connection(connfd); + return Connection((int)connfd); } diff --git a/src/modbusException.cpp b/src/modbusException.cpp index b9c4198..ec29b0d 100644 --- a/src/modbusException.cpp +++ b/src/modbusException.cpp @@ -24,7 +24,7 @@ ModbusException::ModbusException(const std::vector &inputData, if (CRC) { auto CRC = *reinterpret_cast(&inputData[3]); - auto calculatedCRC = utils::calculateCRC(inputData.begin().base(), 3); + auto calculatedCRC = utils::calculateCRC(inputData.data(), 3); if (CRC != calculatedCRC) { _errorCode = utils::ErrorCodeCRCError; @@ -54,8 +54,8 @@ std::vector ModbusException::toRaw() const noexcept { std::vector result(3); result[0] = _slaveId; - result[1] = static_cast(_errorCode | 0b10000000); - result[2] = static_cast(_functionCode); + result[1] = static_cast(_functionCode | 0b10000000); + result[2] = static_cast(_errorCode); return result; } diff --git a/src/modbusRequest.cpp b/src/modbusRequest.cpp index 79c736d..769a74f 100644 --- a/src/modbusRequest.cpp +++ b/src/modbusRequest.cpp @@ -92,7 +92,7 @@ ModbusRequest::ModbusRequest(const std::vector &inputData, bool CRC) { throw ModbusException(utils::InvalidByteOrder); auto recvCRC = *reinterpret_cast(&inputData[crcIndex]); - auto myCRC = utils::calculateCRC(inputData.begin().base(), crcIndex); + auto myCRC = utils::calculateCRC(inputData.data(), crcIndex); if (recvCRC != myCRC) { throw ModbusException(utils::InvalidCRC, _slaveID); @@ -100,7 +100,7 @@ ModbusRequest::ModbusRequest(const std::vector &inputData, bool CRC) { } } catch (const ModbusException &ex) { throw ex; - } catch (const std::exception &ex) { + } catch (const std::exception /*&ex*/) { throw ModbusException(utils::InvalidByteOrder); } } @@ -158,7 +158,7 @@ std::vector ModbusRequest::toRaw() const noexcept { utils::pushUint16(result, value.reg()); } } else { - int end = result.size() - 1; + size_t end = result.size() - 1; for (std::size_t i = 0; i < _values.size(); i++) { if (i % 8 == 0) { result.push_back(0x00); diff --git a/src/modbusResponse.cpp b/src/modbusResponse.cpp index 7166b72..8c9b7bd 100644 --- a/src/modbusResponse.cpp +++ b/src/modbusResponse.cpp @@ -13,9 +13,9 @@ using namespace MB; ModbusResponse::ModbusResponse(uint8_t slaveId, utils::MBFunctionCode functionCode, uint16_t address, uint16_t registersNumber, - std::vector values) + const std::vector &values) : _slaveID(slaveId), _functionCode(functionCode), _address(address), - _registersNumber(registersNumber), _values(std::move(values)) { + _registersNumber(registersNumber), _values(values) { // Force proper modbuscell type switch (functionRegisters()) { case utils::OutputCoils: @@ -31,7 +31,7 @@ ModbusResponse::ModbusResponse(uint8_t slaveId, } } -ModbusResponse::ModbusResponse(std::vector inputData, bool CRC) { +ModbusResponse::ModbusResponse(const std::vector &inputData, bool CRC) { try { if (inputData.size() < 3) throw ModbusException(utils::InvalidByteOrder); @@ -96,7 +96,7 @@ ModbusResponse::ModbusResponse(std::vector inputData, bool CRC) { auto recievedCRC = *reinterpret_cast(&inputData[crcIndex]); - auto myCRC = utils::calculateCRC(inputData.begin().base(), crcIndex); + auto myCRC = utils::calculateCRC(inputData.data(), crcIndex); if (recievedCRC != myCRC) { throw ModbusException(utils::InvalidCRC, _slaveID); @@ -104,7 +104,7 @@ ModbusResponse::ModbusResponse(std::vector inputData, bool CRC) { } } catch (const ModbusException &ex) { throw ex; - } catch (const std::exception &ex) { + } catch (const std::exception /*&ex*/) { throw ModbusException(utils::InvalidByteOrder); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5bb94ac..0503ba0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,11 @@ project(Google_tests) + +if (MSVC) +set(gtest_force_shared_crt on) +endif() + add_subdirectory(googletest) -include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) +include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR} ../include) set(TestFiles MB/ModbusRequestTests.cpp MB/ModbusResponseTests.cpp @@ -10,5 +15,5 @@ set(TestFiles MB/ModbusRequestTests.cpp add_executable(Google_Tests_run ${TestFiles}) -target_link_libraries(Google_Tests_run Modbus) +target_link_libraries(Google_Tests_run Modbus_Core) target_link_libraries(Google_Tests_run gtest gtest_main)