├── QtModbus.pro ├── README.md ├── deployment.pri ├── dll └── libmodbus-5.dll ├── libMb ├── config.h ├── modbus-private.h ├── modbus-rtu-private.h ├── modbus-rtu.h ├── modbus-tcp-private.h ├── modbus-tcp.h ├── modbus-version.h └── modbus.h ├── main.cpp ├── qtmodbus.cpp ├── qtmodbus.h ├── qtmodbus.ui ├── zlibmodbus.cpp └── zlibmodbus.h /QtModbus.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2014-11-24T15:28:57 4 | # 5 | #------------------------------------------------- 6 | CONFIG+=c++11 7 | 8 | QT += core gui 9 | 10 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 11 | 12 | TARGET = QtModbus 13 | TEMPLATE = app 14 | 15 | 16 | # Winsock libs 17 | #win32:LIBS += -lWS2_32 18 | 19 | # Modbus dll location 20 | win32:LIBS += "H:/GitHub/QtModbus/dll/libmodbus-5.dll" 21 | #win32:LIBS += "G:/QtGit/QtModbus/dll/libmodbus-5.dll" 22 | 23 | SOURCES += main.cpp\ 24 | qtmodbus.cpp \ 25 | zlibmodbus.cpp 26 | 27 | HEADERS += qtmodbus.h \ 28 | libMb/config.h \ 29 | libMb/modbus.h \ 30 | libMb/modbus-private.h \ 31 | libMb/modbus-rtu.h \ 32 | libMb/modbus-rtu-private.h \ 33 | libMb/modbus-tcp.h \ 34 | libMb/modbus-tcp-private.h \ 35 | libMb/modbus-version.h \ 36 | zlibmodbus.h 37 | 38 | FORMS += qtmodbus.ui 39 | 40 | OTHER_FILES += \ 41 | dll/libmodbus-5.dll 42 | 43 | # Add more folders to ship with the application, here 44 | folder_01.source = ./dll/. 45 | folder_01.target = ./ 46 | DEPLOYMENTFOLDERS = folder_01 47 | 48 | # Additional import path used to resolve QML modules in Creator's code model 49 | QML_IMPORT_PATH = 50 | 51 | # Deploy Qt Components 52 | include(deployment.pri) 53 | qtcAddDeployment() 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QtModbus 2 | ======== 3 | 4 | Qt5 Modbus example using libModbus 5 | 6 | - A QT5 Wrapper for the libModbus dll. 7 | - A basic working example showing some simple Modbus usage. 8 | - Project build will also try to deploy the included libmodbus-5.dll to the runtime directory, comment out include(deployment.pri) & qtcAddDeployment() from project file if not required. 9 | -------------------------------------------------------------------------------- /deployment.pri: -------------------------------------------------------------------------------- 1 | # This file was generated by an application wizard of Qt Creator. 2 | # The code below handles deployment to Android and Maemo, aswell as copying 3 | # of the application data to shadow build directories on desktop. 4 | # It is recommended not to modify this file, since newer versions of Qt Creator 5 | # may offer an updated version of it. 6 | 7 | defineTest(qtcAddDeployment) { 8 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 9 | item = item$${deploymentfolder} 10 | greaterThan(QT_MAJOR_VERSION, 4) { 11 | itemsources = $${item}.files 12 | } else { 13 | itemsources = $${item}.sources 14 | } 15 | $$itemsources = $$eval($${deploymentfolder}.source) 16 | itempath = $${item}.path 17 | $$itempath= $$eval($${deploymentfolder}.target) 18 | export($$itemsources) 19 | export($$itempath) 20 | DEPLOYMENT += $$item 21 | } 22 | 23 | MAINPROFILEPWD = $$PWD 24 | 25 | android-no-sdk { 26 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 27 | item = item$${deploymentfolder} 28 | itemfiles = $${item}.files 29 | $$itemfiles = $$eval($${deploymentfolder}.source) 30 | itempath = $${item}.path 31 | $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) 32 | export($$itemfiles) 33 | export($$itempath) 34 | INSTALLS += $$item 35 | } 36 | 37 | target.path = /data/user/qt 38 | 39 | export(target.path) 40 | INSTALLS += target 41 | } else:android { 42 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 43 | item = item$${deploymentfolder} 44 | itemfiles = $${item}.files 45 | $$itemfiles = $$eval($${deploymentfolder}.source) 46 | itempath = $${item}.path 47 | $$itempath = /assets/$$eval($${deploymentfolder}.target) 48 | export($$itemfiles) 49 | export($$itempath) 50 | INSTALLS += $$item 51 | } 52 | 53 | x86 { 54 | target.path = /libs/x86 55 | } else: armeabi-v7a { 56 | target.path = /libs/armeabi-v7a 57 | } else { 58 | target.path = /libs/armeabi 59 | } 60 | 61 | export(target.path) 62 | INSTALLS += target 63 | } else:win32 { 64 | copyCommand = 65 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 66 | source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) 67 | source = $$replace(source, /, \\) 68 | sourcePathSegments = $$split(source, \\) 69 | target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) 70 | target = $$replace(target, /, \\) 71 | target ~= s,\\\\\\.?\\\\,\\, 72 | !isEqual(source,$$target) { 73 | !isEmpty(copyCommand):copyCommand += && 74 | isEqual(QMAKE_DIR_SEP, \\) { 75 | copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" 76 | } else { 77 | source = $$replace(source, \\\\, /) 78 | target = $$OUT_PWD/$$eval($${deploymentfolder}.target) 79 | target = $$replace(target, \\\\, /) 80 | copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" 81 | } 82 | } 83 | } 84 | !isEmpty(copyCommand) { 85 | copyCommand = @echo Copying application data... && $$copyCommand 86 | copydeploymentfolders.commands = $$copyCommand 87 | first.depends = $(first) copydeploymentfolders 88 | export(first.depends) 89 | export(copydeploymentfolders.commands) 90 | QMAKE_EXTRA_TARGETS += first copydeploymentfolders 91 | } 92 | } else:ios { 93 | copyCommand = 94 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 95 | source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) 96 | source = $$replace(source, \\\\, /) 97 | target = $CODESIGNING_FOLDER_PATH/$$eval($${deploymentfolder}.target) 98 | target = $$replace(target, \\\\, /) 99 | sourcePathSegments = $$split(source, /) 100 | targetFullPath = $$target/$$last(sourcePathSegments) 101 | targetFullPath ~= s,/\\.?/,/, 102 | !isEqual(source,$$targetFullPath) { 103 | !isEmpty(copyCommand):copyCommand += && 104 | copyCommand += mkdir -p \"$$target\" 105 | copyCommand += && cp -r \"$$source\" \"$$target\" 106 | } 107 | } 108 | !isEmpty(copyCommand) { 109 | copyCommand = echo Copying application data... && $$copyCommand 110 | !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" 111 | QMAKE_POST_LINK += "$$copyCommand" 112 | export(QMAKE_POST_LINK) 113 | } 114 | } else:unix { 115 | maemo5 { 116 | desktopfile.files = $${TARGET}.desktop 117 | desktopfile.path = /usr/share/applications/hildon 118 | icon.files = $${TARGET}64.png 119 | icon.path = /usr/share/icons/hicolor/64x64/apps 120 | } else:!isEmpty(MEEGO_VERSION_MAJOR) { 121 | desktopfile.files = $${TARGET}_harmattan.desktop 122 | desktopfile.path = /usr/share/applications 123 | icon.files = $${TARGET}80.png 124 | icon.path = /usr/share/icons/hicolor/80x80/apps 125 | } else { # Assumed to be a Desktop Unix 126 | copyCommand = 127 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 128 | source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) 129 | source = $$replace(source, \\\\, /) 130 | macx { 131 | target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) 132 | } else { 133 | target = $$OUT_PWD/$$eval($${deploymentfolder}.target) 134 | } 135 | target = $$replace(target, \\\\, /) 136 | sourcePathSegments = $$split(source, /) 137 | targetFullPath = $$target/$$last(sourcePathSegments) 138 | targetFullPath ~= s,/\\.?/,/, 139 | !isEqual(source,$$targetFullPath) { 140 | !isEmpty(copyCommand):copyCommand += && 141 | copyCommand += $(MKDIR) \"$$target\" 142 | copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" 143 | } 144 | } 145 | !isEmpty(copyCommand) { 146 | copyCommand = @echo Copying application data... && $$copyCommand 147 | copydeploymentfolders.commands = $$copyCommand 148 | first.depends = $(first) copydeploymentfolders 149 | export(first.depends) 150 | export(copydeploymentfolders.commands) 151 | QMAKE_EXTRA_TARGETS += first copydeploymentfolders 152 | } 153 | } 154 | !isEmpty(target.path) { 155 | installPrefix = $${target.path} 156 | } else { 157 | installPrefix = /opt/$${TARGET} 158 | } 159 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 160 | item = item$${deploymentfolder} 161 | itemfiles = $${item}.files 162 | $$itemfiles = $$eval($${deploymentfolder}.source) 163 | itempath = $${item}.path 164 | $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) 165 | export($$itemfiles) 166 | export($$itempath) 167 | INSTALLS += $$item 168 | } 169 | 170 | !isEmpty(desktopfile.path) { 171 | export(icon.files) 172 | export(icon.path) 173 | export(desktopfile.files) 174 | export(desktopfile.path) 175 | INSTALLS += icon desktopfile 176 | } 177 | 178 | isEmpty(target.path) { 179 | target.path = $${installPrefix}/bin 180 | export(target.path) 181 | } 182 | INSTALLS += target 183 | } 184 | 185 | export (ICON) 186 | export (INSTALLS) 187 | export (DEPLOYMENT) 188 | export (LIBS) 189 | export (QMAKE_EXTRA_TARGETS) 190 | } 191 | -------------------------------------------------------------------------------- /dll/libmodbus-5.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oozenthor/QtModbus/dab9bc3349015309f10cbd18b2f011eb61ba2999/dll/libmodbus-5.dll -------------------------------------------------------------------------------- /libMb/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define to 1 if you have the `accept4' function. */ 5 | /* #undef HAVE_ACCEPT4 */ 6 | 7 | /* Define to 1 if you have the header file. */ 8 | /* #undef HAVE_ARPA_INET_H */ 9 | 10 | /* Define to 1 if you have the header file. */ 11 | /* #undef HAVE_BYTESWAP_H */ 12 | 13 | /* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you 14 | don't. */ 15 | #define HAVE_DECL_TIOCM_RTS 0 16 | 17 | /* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you 18 | don't. */ 19 | #define HAVE_DECL_TIOCSRS485 0 20 | 21 | /* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you 22 | don't. */ 23 | #define HAVE_DECL___CYGWIN__ 0 24 | 25 | /* Define to 1 if you have the header file. */ 26 | /* #undef HAVE_DLFCN_H */ 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_ERRNO_H 1 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #define HAVE_FCNTL_H 1 33 | 34 | /* Define to 1 if you have the `fork' function. */ 35 | /* #undef HAVE_FORK */ 36 | 37 | /* Define to 1 if you have the `getaddrinfo' function. */ 38 | /* #undef HAVE_GETADDRINFO */ 39 | 40 | /* Define to 1 if you have the `gettimeofday' function. */ 41 | #define HAVE_GETTIMEOFDAY 1 42 | 43 | /* Define to 1 if you have the `inet_ntoa' function. */ 44 | /* #undef HAVE_INET_NTOA */ 45 | 46 | /* Define to 1 if you have the header file. */ 47 | #define HAVE_INTTYPES_H 1 48 | 49 | /* Define to 1 if you have the header file. */ 50 | #define HAVE_LIMITS_H 1 51 | 52 | /* Define to 1 if you have the header file. */ 53 | /* #undef HAVE_LINUX_SERIAL_H */ 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #define HAVE_MEMORY_H 1 57 | 58 | /* Define to 1 if you have the `memset' function. */ 59 | #define HAVE_MEMSET 1 60 | 61 | /* Define to 1 if you have the header file. */ 62 | /* #undef HAVE_NETDB_H */ 63 | 64 | /* Define to 1 if you have the header file. */ 65 | /* #undef HAVE_NETINET_IN_H */ 66 | 67 | /* Define to 1 if you have the header file. */ 68 | /* #undef HAVE_NETINET_TCP_H */ 69 | 70 | /* Define to 1 if you have the `select' function. */ 71 | /* #undef HAVE_SELECT */ 72 | 73 | /* Define to 1 if you have the `socket' function. */ 74 | /* #undef HAVE_SOCKET */ 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #define HAVE_STDINT_H 1 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #define HAVE_STDLIB_H 1 81 | 82 | /* Define to 1 if you have the `strerror' function. */ 83 | #define HAVE_STRERROR 1 84 | 85 | /* Define to 1 if you have the header file. */ 86 | #define HAVE_STRINGS_H 1 87 | 88 | /* Define to 1 if you have the header file. */ 89 | #define HAVE_STRING_H 1 90 | 91 | /* Define to 1 if you have the `strlcpy' function. */ 92 | /* #undef HAVE_STRLCPY */ 93 | 94 | /* Define to 1 if you have the header file. */ 95 | /* #undef HAVE_SYS_IOCTL_H */ 96 | 97 | /* Define to 1 if you have the header file. */ 98 | /* #undef HAVE_SYS_SOCKET_H */ 99 | 100 | /* Define to 1 if you have the header file. */ 101 | #define HAVE_SYS_STAT_H 1 102 | 103 | /* Define to 1 if you have the header file. */ 104 | #define HAVE_SYS_TIME_H 1 105 | 106 | /* Define to 1 if you have the header file. */ 107 | #define HAVE_SYS_TYPES_H 1 108 | 109 | /* Define to 1 if you have the header file. */ 110 | /* #undef HAVE_TERMIOS_H */ 111 | 112 | /* Define to 1 if you have the header file. */ 113 | #define HAVE_TIME_H 1 114 | 115 | /* Define to 1 if you have the header file. */ 116 | #define HAVE_UNISTD_H 1 117 | 118 | /* Define to 1 if you have the `vfork' function. */ 119 | /* #undef HAVE_VFORK */ 120 | 121 | /* Define to 1 if you have the header file. */ 122 | /* #undef HAVE_VFORK_H */ 123 | 124 | /* Define to 1 if you have the header file. */ 125 | #define HAVE_WINSOCK2_H 1 126 | 127 | /* Define to 1 if `fork' works. */ 128 | /* #undef HAVE_WORKING_FORK */ 129 | 130 | /* Define to 1 if `vfork' works. */ 131 | /* #undef HAVE_WORKING_VFORK */ 132 | 133 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 134 | */ 135 | #define LT_OBJDIR ".libs/" 136 | 137 | /* Name of package */ 138 | #define PACKAGE "libmodbus" 139 | 140 | /* Define to the address where bug reports for this package should be sent. */ 141 | #define PACKAGE_BUGREPORT "https://github.com/stephane/libmodbus/issues" 142 | 143 | /* Define to the full name of this package. */ 144 | #define PACKAGE_NAME "libmodbus" 145 | 146 | /* Define to the full name and version of this package. */ 147 | #define PACKAGE_STRING "libmodbus 3.1.1" 148 | 149 | /* Define to the one symbol short name of this package. */ 150 | #define PACKAGE_TARNAME "libmodbus" 151 | 152 | /* Define to the home page for this package. */ 153 | #define PACKAGE_URL "http://libmodbus.org/" 154 | 155 | /* Define to the version of this package. */ 156 | #define PACKAGE_VERSION "3.1.1" 157 | 158 | /* Define to 1 if you have the ANSI C header files. */ 159 | #define STDC_HEADERS 1 160 | 161 | /* Enable extensions on AIX 3, Interix. */ 162 | #ifndef _ALL_SOURCE 163 | # define _ALL_SOURCE 1 164 | #endif 165 | /* Enable GNU extensions on systems that have them. */ 166 | #ifndef _GNU_SOURCE 167 | # define _GNU_SOURCE 1 168 | #endif 169 | /* Enable threading extensions on Solaris. */ 170 | #ifndef _POSIX_PTHREAD_SEMANTICS 171 | # define _POSIX_PTHREAD_SEMANTICS 1 172 | #endif 173 | /* Enable extensions on HP NonStop. */ 174 | #ifndef _TANDEM_SOURCE 175 | # define _TANDEM_SOURCE 1 176 | #endif 177 | /* Enable general extensions on Solaris. */ 178 | #ifndef __EXTENSIONS__ 179 | # define __EXTENSIONS__ 1 180 | #endif 181 | 182 | 183 | /* Version number of package */ 184 | #define VERSION "3.1.1" 185 | 186 | /* _ */ 187 | #define WINVER 0x0501 188 | 189 | /* Number of bits in a file offset, on hosts where this is settable. */ 190 | /* #undef _FILE_OFFSET_BITS */ 191 | 192 | /* Define for large files, on AIX-style hosts. */ 193 | /* #undef _LARGE_FILES */ 194 | 195 | /* Define to 1 if on MINIX. */ 196 | /* #undef _MINIX */ 197 | 198 | /* Define to 2 if the system does not provide POSIX.1 features except with 199 | this defined. */ 200 | /* #undef _POSIX_1_SOURCE */ 201 | 202 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 203 | /* #undef _POSIX_SOURCE */ 204 | 205 | /* Define to `int' if does not define. */ 206 | /* #undef pid_t */ 207 | 208 | /* Define as `fork' if `vfork' does not work. */ 209 | #define vfork fork 210 | -------------------------------------------------------------------------------- /libMb/modbus-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2010-2012 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_PRIVATE_H 20 | #define MODBUS_PRIVATE_H 21 | 22 | #ifndef _MSC_VER 23 | # include 24 | # include 25 | #else 26 | # include "stdint.h" 27 | # include 28 | typedef int ssize_t; 29 | #endif 30 | #include 31 | #include "config.h" 32 | 33 | #include "modbus.h" 34 | 35 | MODBUS_BEGIN_DECLS 36 | 37 | /* It's not really the minimal length (the real one is report slave ID 38 | * in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP 39 | * communications to read many values or write a single one. 40 | * Maximum between : 41 | * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2) 42 | * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2) 43 | */ 44 | #define _MIN_REQ_LENGTH 12 45 | 46 | #define _REPORT_SLAVE_ID 180 47 | 48 | #define _MODBUS_EXCEPTION_RSP_LENGTH 5 49 | 50 | /* Timeouts in microsecond (0.5 s) */ 51 | #define _RESPONSE_TIMEOUT 500000 52 | #define _BYTE_TIMEOUT 500000 53 | 54 | typedef enum { 55 | _MODBUS_BACKEND_TYPE_RTU=0, 56 | _MODBUS_BACKEND_TYPE_TCP 57 | } modbus_backend_type_t; 58 | 59 | /* 60 | * ---------- Request Indication ---------- 61 | * | Client | ---------------------->| Server | 62 | * ---------- Confirmation Response ---------- 63 | */ 64 | typedef enum { 65 | /* Request message on the server side */ 66 | MSG_INDICATION, 67 | /* Request message on the client side */ 68 | MSG_CONFIRMATION 69 | } msg_type_t; 70 | 71 | /* This structure reduces the number of params in functions and so 72 | * optimizes the speed of execution (~ 37%). */ 73 | typedef struct _sft { 74 | int slave; 75 | int function; 76 | int t_id; 77 | } sft_t; 78 | 79 | typedef struct _modbus_backend { 80 | unsigned int backend_type; 81 | unsigned int header_length; 82 | unsigned int checksum_length; 83 | unsigned int max_adu_length; 84 | int (*set_slave) (modbus_t *ctx, int slave); 85 | int (*build_request_basis) (modbus_t *ctx, int function, int addr, 86 | int nb, uint8_t *req); 87 | int (*build_response_basis) (sft_t *sft, uint8_t *rsp); 88 | int (*prepare_response_tid) (const uint8_t *req, int *req_length); 89 | int (*send_msg_pre) (uint8_t *req, int req_length); 90 | ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); 91 | int (*receive) (modbus_t *ctx, uint8_t *req); 92 | ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); 93 | int (*check_integrity) (modbus_t *ctx, uint8_t *msg, 94 | const int msg_length); 95 | int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req, 96 | const uint8_t *rsp, int rsp_length); 97 | int (*connect) (modbus_t *ctx); 98 | void (*close) (modbus_t *ctx); 99 | int (*flush) (modbus_t *ctx); 100 | int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length); 101 | void (*free) (modbus_t *ctx); 102 | } modbus_backend_t; 103 | 104 | struct _modbus { 105 | /* Slave address */ 106 | int slave; 107 | /* Socket or file descriptor */ 108 | int s; 109 | int debug; 110 | int error_recovery; 111 | struct timeval response_timeout; 112 | struct timeval byte_timeout; 113 | const modbus_backend_t *backend; 114 | void *backend_data; 115 | }; 116 | 117 | void _modbus_init_common(modbus_t *ctx); 118 | void _error_print(modbus_t *ctx, const char *context); 119 | int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type); 120 | 121 | #ifndef HAVE_STRLCPY 122 | size_t strlcpy(char *dest, const char *src, size_t dest_size); 123 | #endif 124 | 125 | MODBUS_END_DECLS 126 | 127 | #endif /* MODBUS_PRIVATE_H */ 128 | -------------------------------------------------------------------------------- /libMb/modbus-rtu-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2001-2011 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_RTU_PRIVATE_H 20 | #define MODBUS_RTU_PRIVATE_H 21 | 22 | #ifndef _MSC_VER 23 | #include 24 | #else 25 | #include "stdint.h" 26 | #endif 27 | 28 | #if defined(_WIN32) 29 | #include 30 | #else 31 | #include 32 | #endif 33 | 34 | #define _MODBUS_RTU_HEADER_LENGTH 1 35 | #define _MODBUS_RTU_PRESET_REQ_LENGTH 6 36 | #define _MODBUS_RTU_PRESET_RSP_LENGTH 2 37 | 38 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 39 | 40 | /* Time waited beetween the RTS switch before transmit data or after transmit 41 | data before to read */ 42 | #define _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH 10000 43 | 44 | #if defined(_WIN32) 45 | #if !defined(ENOTSUP) 46 | #define ENOTSUP WSAEOPNOTSUPP 47 | #endif 48 | 49 | /* WIN32: struct containing serial handle and a receive buffer */ 50 | #define PY_BUF_SIZE 512 51 | struct win32_ser { 52 | /* File handle */ 53 | HANDLE fd; 54 | /* Receive buffer */ 55 | uint8_t buf[PY_BUF_SIZE]; 56 | /* Received chars */ 57 | DWORD n_bytes; 58 | }; 59 | #endif /* _WIN32 */ 60 | 61 | typedef struct _modbus_rtu { 62 | /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */ 63 | char *device; 64 | /* Bauds: 9600, 19200, 57600, 115200, etc */ 65 | int baud; 66 | /* Data bit */ 67 | uint8_t data_bit; 68 | /* Stop bit */ 69 | uint8_t stop_bit; 70 | /* Parity: 'N', 'O', 'E' */ 71 | char parity; 72 | #if defined(_WIN32) 73 | struct win32_ser w_ser; 74 | DCB old_dcb; 75 | #else 76 | /* Save old termios settings */ 77 | struct termios old_tios; 78 | #endif 79 | #if HAVE_DECL_TIOCSRS485 80 | int serial_mode; 81 | #endif 82 | #if HAVE_DECL_TIOCM_RTS 83 | int rts; 84 | int onebyte_time; 85 | #endif 86 | /* To handle many slaves on the same link */ 87 | int confirmation_to_ignore; 88 | } modbus_rtu_t; 89 | 90 | #endif /* MODBUS_RTU_PRIVATE_H */ 91 | -------------------------------------------------------------------------------- /libMb/modbus-rtu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2001-2011 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_RTU_H 20 | #define MODBUS_RTU_H 21 | 22 | #include "modbus.h" 23 | 24 | MODBUS_BEGIN_DECLS 25 | 26 | /* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 27 | * RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes 28 | */ 29 | #define MODBUS_RTU_MAX_ADU_LENGTH 256 30 | 31 | MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity, 32 | int data_bit, int stop_bit); 33 | 34 | #define MODBUS_RTU_RS232 0 35 | #define MODBUS_RTU_RS485 1 36 | 37 | MODBUS_API int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); 38 | MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx); 39 | 40 | #define MODBUS_RTU_RTS_NONE 0 41 | #define MODBUS_RTU_RTS_UP 1 42 | #define MODBUS_RTU_RTS_DOWN 2 43 | 44 | MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); 45 | MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); 46 | 47 | MODBUS_END_DECLS 48 | 49 | #endif /* MODBUS_RTU_H */ 50 | -------------------------------------------------------------------------------- /libMb/modbus-tcp-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2001-2011 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_TCP_PRIVATE_H 20 | #define MODBUS_TCP_PRIVATE_H 21 | 22 | #define _MODBUS_TCP_HEADER_LENGTH 7 23 | #define _MODBUS_TCP_PRESET_REQ_LENGTH 12 24 | #define _MODBUS_TCP_PRESET_RSP_LENGTH 8 25 | 26 | #define _MODBUS_TCP_CHECKSUM_LENGTH 0 27 | 28 | /* In both structures, the transaction ID must be placed on first position 29 | to have a quick access not dependant of the TCP backend */ 30 | typedef struct _modbus_tcp { 31 | /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b 32 | (page 23/46): 33 | The transaction identifier is used to associate the future response 34 | with the request. This identifier is unique on each TCP connection. */ 35 | uint16_t t_id; 36 | /* TCP port */ 37 | int port; 38 | /* IP address */ 39 | char ip[16]; 40 | } modbus_tcp_t; 41 | 42 | #define _MODBUS_TCP_PI_NODE_LENGTH 1025 43 | #define _MODBUS_TCP_PI_SERVICE_LENGTH 32 44 | 45 | typedef struct _modbus_tcp_pi { 46 | /* Transaction ID */ 47 | uint16_t t_id; 48 | /* TCP port */ 49 | int port; 50 | /* Node */ 51 | char node[_MODBUS_TCP_PI_NODE_LENGTH]; 52 | /* Service */ 53 | char service[_MODBUS_TCP_PI_SERVICE_LENGTH]; 54 | } modbus_tcp_pi_t; 55 | 56 | #endif /* MODBUS_TCP_PRIVATE_H */ 57 | -------------------------------------------------------------------------------- /libMb/modbus-tcp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2001-2010 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_TCP_H 20 | #define MODBUS_TCP_H 21 | 22 | #include "modbus.h" 23 | 24 | MODBUS_BEGIN_DECLS 25 | 26 | #if defined(_WIN32) && !defined(__CYGWIN__) 27 | /* Win32 with MinGW, supplement to */ 28 | #include 29 | #if !defined(ECONNRESET) 30 | #define ECONNRESET WSAECONNRESET 31 | #endif 32 | #if !defined(ECONNREFUSED) 33 | #define ECONNREFUSED WSAECONNREFUSED 34 | #endif 35 | #if !defined(ETIMEDOUT) 36 | #define ETIMEDOUT WSAETIMEDOUT 37 | #endif 38 | #if !defined(ENOPROTOOPT) 39 | #define ENOPROTOOPT WSAENOPROTOOPT 40 | #endif 41 | #if !defined(EINPROGRESS) 42 | #define EINPROGRESS WSAEINPROGRESS 43 | #endif 44 | #endif 45 | 46 | #define MODBUS_TCP_DEFAULT_PORT 502 47 | #define MODBUS_TCP_SLAVE 0xFF 48 | 49 | /* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 50 | * TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes 51 | */ 52 | #define MODBUS_TCP_MAX_ADU_LENGTH 260 53 | 54 | MODBUS_API modbus_t* modbus_new_tcp(const char *ip_address, int port); 55 | MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection); 56 | MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s); 57 | 58 | MODBUS_API modbus_t* modbus_new_tcp_pi(const char *node, const char *service); 59 | MODBUS_API int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection); 60 | MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s); 61 | 62 | MODBUS_END_DECLS 63 | 64 | #endif /* MODBUS_TCP_H */ 65 | -------------------------------------------------------------------------------- /libMb/modbus-version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2010-2014 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_VERSION_H 20 | #define MODBUS_VERSION_H 21 | 22 | /* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */ 23 | #define LIBMODBUS_VERSION_MAJOR (3) 24 | 25 | /* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */ 26 | #define LIBMODBUS_VERSION_MINOR (1) 27 | 28 | /* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */ 29 | #define LIBMODBUS_VERSION_MICRO (1) 30 | 31 | /* The full version, like 1.2.3 */ 32 | #define LIBMODBUS_VERSION 3.1.1 33 | 34 | /* The full version, in string form (suited for string concatenation) 35 | */ 36 | #define LIBMODBUS_VERSION_STRING "3.1.1" 37 | 38 | /* Numerically encoded version, like 0x010203 */ 39 | #define LIBMODBUS_VERSION_HEX ((LIBMODBUS_VERSION_MAJOR << 24) | \ 40 | (LIBMODBUS_VERSION_MINOR << 16) | \ 41 | (LIBMODBUS_VERSION_MICRO << 8)) 42 | 43 | /* Evaluates to True if the version is greater than @major, @minor and @micro 44 | */ 45 | #define LIBMODBUS_VERSION_CHECK(major,minor,micro) \ 46 | (LIBMODBUS_VERSION_MAJOR > (major) || \ 47 | (LIBMODBUS_VERSION_MAJOR == (major) && \ 48 | LIBMODBUS_VERSION_MINOR > (minor)) || \ 49 | (LIBMODBUS_VERSION_MAJOR == (major) && \ 50 | LIBMODBUS_VERSION_MINOR == (minor) && \ 51 | LIBMODBUS_VERSION_MICRO >= (micro))) 52 | 53 | #endif /* MODBUS_VERSION_H */ 54 | -------------------------------------------------------------------------------- /libMb/modbus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2001-2013 Stéphane Raimbault 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef MODBUS_H 20 | #define MODBUS_H 21 | 22 | /* Add this for macros that defined unix flavor */ 23 | #if (defined(__unix__) || defined(unix)) && !defined(USG) 24 | #include 25 | #endif 26 | 27 | #ifndef _MSC_VER 28 | #include 29 | #else 30 | #include "stdint.h" 31 | #endif 32 | 33 | #include "modbus-version.h" 34 | 35 | #if defined(_MSC_VER) 36 | # if defined(DLLBUILD) 37 | /* define DLLBUILD when building the DLL */ 38 | # define MODBUS_API __declspec(dllexport) 39 | # else 40 | # define MODBUS_API __declspec(dllimport) 41 | # endif 42 | #else 43 | # define MODBUS_API 44 | #endif 45 | 46 | #ifdef __cplusplus 47 | # define MODBUS_BEGIN_DECLS extern "C" { 48 | # define MODBUS_END_DECLS } 49 | #else 50 | # define MODBUS_BEGIN_DECLS 51 | # define MODBUS_END_DECLS 52 | #endif 53 | 54 | MODBUS_BEGIN_DECLS 55 | 56 | #ifndef FALSE 57 | #define FALSE 0 58 | #endif 59 | 60 | #ifndef TRUE 61 | #define TRUE 1 62 | #endif 63 | 64 | #ifndef OFF 65 | #define OFF 0 66 | #endif 67 | 68 | #ifndef ON 69 | #define ON 1 70 | #endif 71 | 72 | /* Modbus function codes */ 73 | #define MODBUS_FC_READ_COILS 0x01 74 | #define MODBUS_FC_READ_DISCRETE_INPUTS 0x02 75 | #define MODBUS_FC_READ_HOLDING_REGISTERS 0x03 76 | #define MODBUS_FC_READ_INPUT_REGISTERS 0x04 77 | #define MODBUS_FC_WRITE_SINGLE_COIL 0x05 78 | #define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 79 | #define MODBUS_FC_READ_EXCEPTION_STATUS 0x07 80 | #define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F 81 | #define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 82 | #define MODBUS_FC_REPORT_SLAVE_ID 0x11 83 | #define MODBUS_FC_MASK_WRITE_REGISTER 0x16 84 | #define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 85 | 86 | #define MODBUS_BROADCAST_ADDRESS 0 87 | 88 | /* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) 89 | * Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0) 90 | * (chapter 6 section 11 page 29) 91 | * Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0) 92 | */ 93 | #define MODBUS_MAX_READ_BITS 2000 94 | #define MODBUS_MAX_WRITE_BITS 1968 95 | 96 | /* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15) 97 | * Quantity of Registers to read (2 bytes): 1 to 125 (0x7D) 98 | * (chapter 6 section 12 page 31) 99 | * Quantity of Registers to write (2 bytes) 1 to 123 (0x7B) 100 | * (chapter 6 section 17 page 38) 101 | * Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79) 102 | */ 103 | #define MODBUS_MAX_READ_REGISTERS 125 104 | #define MODBUS_MAX_WRITE_REGISTERS 123 105 | #define MODBUS_MAX_WR_WRITE_REGISTERS 121 106 | #define MODBUS_MAX_WR_READ_REGISTERS 125 107 | 108 | /* The size of the MODBUS PDU is limited by the size constraint inherited from 109 | * the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 110 | * bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server 111 | * address (1 byte) - CRC (2 bytes) = 253 bytes. 112 | * 113 | * Consequently: 114 | * - RS232 / RS485 ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 115 | * 256 bytes. 116 | * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes. 117 | */ 118 | #define MODBUS_MAX_PDU_LENGTH 253 119 | 120 | /* Random number to avoid errno conflicts */ 121 | #define MODBUS_ENOBASE 112345678 122 | 123 | /* Protocol exceptions */ 124 | enum { 125 | MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01, 126 | MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, 127 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, 128 | MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE, 129 | MODBUS_EXCEPTION_ACKNOWLEDGE, 130 | MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY, 131 | MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE, 132 | MODBUS_EXCEPTION_MEMORY_PARITY, 133 | MODBUS_EXCEPTION_NOT_DEFINED, 134 | MODBUS_EXCEPTION_GATEWAY_PATH, 135 | MODBUS_EXCEPTION_GATEWAY_TARGET, 136 | MODBUS_EXCEPTION_MAX 137 | }; 138 | 139 | #define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION) 140 | #define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS) 141 | #define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE) 142 | #define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE) 143 | #define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE) 144 | #define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY) 145 | #define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE) 146 | #define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY) 147 | #define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH) 148 | #define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET) 149 | 150 | /* Native libmodbus error codes */ 151 | #define EMBBADCRC (EMBXGTAR + 1) 152 | #define EMBBADDATA (EMBXGTAR + 2) 153 | #define EMBBADEXC (EMBXGTAR + 3) 154 | #define EMBUNKEXC (EMBXGTAR + 4) 155 | #define EMBMDATA (EMBXGTAR + 5) 156 | #define EMBBADSLAVE (EMBXGTAR + 6) 157 | 158 | extern const unsigned int libmodbus_version_major; 159 | extern const unsigned int libmodbus_version_minor; 160 | extern const unsigned int libmodbus_version_micro; 161 | 162 | typedef struct _modbus modbus_t; 163 | 164 | typedef struct { 165 | int nb_bits; 166 | int nb_input_bits; 167 | int nb_input_registers; 168 | int nb_registers; 169 | uint8_t *tab_bits; 170 | uint8_t *tab_input_bits; 171 | uint16_t *tab_input_registers; 172 | uint16_t *tab_registers; 173 | } modbus_mapping_t; 174 | 175 | typedef enum 176 | { 177 | MODBUS_ERROR_RECOVERY_NONE = 0, 178 | MODBUS_ERROR_RECOVERY_LINK = (1<<1), 179 | MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2) 180 | } modbus_error_recovery_mode; 181 | 182 | MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave); 183 | MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery); 184 | MODBUS_API int modbus_set_socket(modbus_t *ctx, int s); 185 | MODBUS_API int modbus_get_socket(modbus_t *ctx); 186 | 187 | MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); 188 | MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec); 189 | 190 | MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); 191 | MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec); 192 | 193 | MODBUS_API int modbus_get_header_length(modbus_t *ctx); 194 | 195 | MODBUS_API int modbus_connect(modbus_t *ctx); 196 | MODBUS_API void modbus_close(modbus_t *ctx); 197 | 198 | MODBUS_API void modbus_free(modbus_t *ctx); 199 | 200 | MODBUS_API int modbus_flush(modbus_t *ctx); 201 | MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag); 202 | 203 | MODBUS_API const char *modbus_strerror(int errnum); 204 | 205 | MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); 206 | MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); 207 | MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); 208 | MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); 209 | MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); 210 | MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, int value); 211 | MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data); 212 | MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data); 213 | MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); 214 | MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, 215 | const uint16_t *src, int read_addr, int read_nb, 216 | uint16_t *dest); 217 | MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); 218 | 219 | MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, 220 | int nb_registers, int nb_input_registers); 221 | MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); 222 | 223 | MODBUS_API int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length); 224 | 225 | MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req); 226 | 227 | MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp); 228 | 229 | MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req, 230 | int req_length, modbus_mapping_t *mb_mapping); 231 | MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, 232 | unsigned int exception_code); 233 | 234 | /** 235 | * UTILS FUNCTIONS 236 | **/ 237 | 238 | #define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF) 239 | #define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF) 240 | #define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) ((tab_int16[(index)] << 16) + tab_int16[(index) + 1]) 241 | #define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) ((tab_int8[(index)] << 8) + tab_int8[(index) + 1]) 242 | #define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \ 243 | do { \ 244 | tab_int8[(index)] = (value) >> 8; \ 245 | tab_int8[(index) + 1] = (value) & 0xFF; \ 246 | } while (0) 247 | 248 | MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value); 249 | MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits, 250 | const uint8_t *tab_byte); 251 | MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits); 252 | MODBUS_API float modbus_get_float(const uint16_t *src); 253 | MODBUS_API float modbus_get_float_dcba(const uint16_t *src); 254 | MODBUS_API void modbus_set_float(float f, uint16_t *dest); 255 | MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest); 256 | 257 | #include "modbus-tcp.h" 258 | #include "modbus-rtu.h" 259 | 260 | MODBUS_END_DECLS 261 | 262 | #endif /* MODBUS_H */ 263 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "qtmodbus.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | QtModbus w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /qtmodbus.cpp: -------------------------------------------------------------------------------- 1 | #include "qtmodbus.h" 2 | #include "ui_qtmodbus.h" 3 | 4 | QtModbus::QtModbus(QWidget *parent) : 5 | QMainWindow(parent), 6 | ui(new Ui::QtModbus) 7 | { 8 | ui->setupUi(this); 9 | 10 | } 11 | 12 | QtModbus::~QtModbus() 13 | { 14 | delete ui; 15 | } 16 | 17 | void QtModbus::on_connectButton_clicked() 18 | { 19 | if (!mb.connect()) { 20 | qDebug() << "fail connect"; 21 | QApplication::exit(-1); 22 | } 23 | } 24 | 25 | void QtModbus::on_writeButton_clicked() 26 | { 27 | bool ok; 28 | quint32 mbVal = QString(ui->writeEdit->text()).toUInt(&ok); 29 | if (!mb.write(1, mbVal)) { 30 | qDebug() << "fail write"; 31 | QApplication::exit(-1); 32 | } 33 | } 34 | 35 | void QtModbus::on_readButton_clicked() 36 | { 37 | ui->readEdit->setText(QString("%1").arg(mb.read(1))); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /qtmodbus.h: -------------------------------------------------------------------------------- 1 | #ifndef QTMODBUS_H 2 | #define QTMODBUS_H 3 | 4 | #include 5 | #include 6 | #include "zlibmodbus.h" 7 | 8 | namespace Ui { 9 | class QtModbus; 10 | } 11 | 12 | class QtModbus : public QMainWindow 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit QtModbus(QWidget *parent = 0); 18 | ~QtModbus(); 19 | 20 | private slots: 21 | void on_writeButton_clicked(); 22 | void on_readButton_clicked(); 23 | void on_connectButton_clicked(); 24 | 25 | private: 26 | Ui::QtModbus *ui; 27 | 28 | ZLibModbus mb; //libModbus wrapper 29 | }; 30 | 31 | #endif // QTMODBUS_H 32 | -------------------------------------------------------------------------------- /qtmodbus.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | QtModbus 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | QtModbus 15 | 16 | 17 | 18 | 19 | 20 | 50 21 | 50 22 | 75 23 | 23 24 | 25 | 26 | 27 | Connect 28 | 29 | 30 | 31 | 32 | 33 | 50 34 | 90 35 | 181 36 | 41 37 | 38 | 39 | 40 | 41 | 42 | 43 | Write 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 12 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 50 62 | 140 63 | 181 64 | 31 65 | 66 | 67 | 68 | 69 | 70 | 71 | Read 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 12 80 | 81 | 82 | 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 0 94 | 0 95 | 400 96 | 21 97 | 98 | 99 | 100 | 101 | 102 | TopToolBarArea 103 | 104 | 105 | false 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /zlibmodbus.cpp: -------------------------------------------------------------------------------- 1 | #include "zlibmodbus.h" 2 | 3 | ZLibModbus::ZLibModbus() 4 | { 5 | } 6 | 7 | ZLibModbus::~ZLibModbus() 8 | { 9 | qDebug() << "Closing modbus connection"; 10 | modbus_close(ctx); // Close the connection 11 | modbus_free(ctx); 12 | } 13 | 14 | bool ZLibModbus::connect() 15 | { 16 | ctx = modbus_new_tcp("127.0.0.1", 502); 17 | 18 | if (ctx == NULL) { 19 | qDebug() << "Unable to allocate libmodbus context"; 20 | return(false); 21 | } 22 | modbus_set_debug(ctx, FALSE); 23 | 24 | if (modbus_connect(ctx) == -1) { 25 | qDebug() << "Connection failed:" << modbus_strerror(errno) << errno; 26 | modbus_free(ctx); 27 | return(false); 28 | } 29 | 30 | modbus_set_debug(ctx, FALSE); //Set modbus library verbosity to "off" 31 | 32 | // Allocate and initialize the memory to store the bits 33 | // mbb = (uint8_t *) malloc(MAXIMUM_BIT_POINTS * sizeof(uint8_t)); 34 | // memset(mbb, 0, MAXIMUM_BIT_POINTS * sizeof(uint8_t)); 35 | 36 | // Allocate and initialize the memory to store the registers 37 | mbw = (uint16_t *) malloc(MAXIMUM_WORD_POINTS * sizeof(uint16_t)); 38 | memset(mbw, 0, MAXIMUM_WORD_POINTS * sizeof(uint16_t)); 39 | 40 | qDebug() << "Connected"; 41 | return(true); 42 | } 43 | 44 | bool ZLibModbus::write(quint16 address, quint16 writeValue) 45 | { 46 | uint16_t modbus_address = static_cast(address); 47 | uint16_t modbus_value = static_cast(writeValue); 48 | 49 | rc = modbus_write_register(ctx, modbus_address, modbus_value); 50 | if (rc == 1) { 51 | qDebug() << "Address:" << modbus_address << ",Value:" << modbus_value << "written"; 52 | return(true); 53 | } else { 54 | qDebug() << "Write FAILED\n"; 55 | return(false); 56 | } 57 | } 58 | 59 | quint16 ZLibModbus::read(quint16 address) 60 | { 61 | uint16_t modbus_address = static_cast(address); 62 | 63 | rc = modbus_read_registers(ctx, modbus_address, 1, mbw); 64 | if (rc == 1) { 65 | qDebug() << "Address:" << modbus_address << ",Value:" << mbw[0] << "read"; 66 | return(static_cast(mbw[0])); 67 | } else { 68 | qDebug() << "Read FAILED\n"; 69 | return(0); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /zlibmodbus.h: -------------------------------------------------------------------------------- 1 | #ifndef ZLIBMODBUS_H 2 | #define ZLIBMODBUS_H 3 | 4 | #define MAXIMUM_WORD_POINTS 40 //maximum holding registers read at a time limit 5 | #define MAXIMUM_BIT_POINTS 40 //maximum relay read at a time limit 6 | 7 | #include 8 | #include 9 | #include "libMb/modbus.h" 10 | 11 | class ZLibModbus 12 | { 13 | public: 14 | ZLibModbus(); 15 | ~ZLibModbus(); 16 | 17 | bool connect(); 18 | bool write(quint16 address, quint16 writeValue); 19 | quint16 read(quint16 address); 20 | 21 | private: 22 | modbus_t *ctx; //Modbus connection context 23 | int rc; //Modbus call return value 24 | uint16_t *mbw; //Modbus word holding array 25 | }; 26 | 27 | #endif // ZLIBMODBUS_H 28 | --------------------------------------------------------------------------------