├── .clang-format ├── .github └── workflows │ ├── clang-format.yml │ └── cmake-multi-platform.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── Doxyfile ├── LICENSE ├── README.md ├── docs └── html │ ├── Serial_2connection_8hpp_source.html │ ├── TCP_2connection_8hpp_source.html │ ├── annotated.html │ ├── bc_s.png │ ├── bc_sd.png │ ├── bdwn.png │ ├── classMB_1_1ModbusCell-members.html │ ├── classMB_1_1ModbusCell.html │ ├── classMB_1_1ModbusException-members.html │ ├── classMB_1_1ModbusException.html │ ├── classMB_1_1ModbusException.png │ ├── classMB_1_1ModbusRequest-members.html │ ├── classMB_1_1ModbusRequest.html │ ├── classMB_1_1ModbusResponse-members.html │ ├── classMB_1_1ModbusResponse.html │ ├── classMB_1_1Serial_1_1Connection-members.html │ ├── classMB_1_1Serial_1_1Connection.html │ ├── classMB_1_1TCP_1_1Connection-members.html │ ├── classMB_1_1TCP_1_1Connection.html │ ├── classMB_1_1TCP_1_1Server-members.html │ ├── classMB_1_1TCP_1_1Server.html │ ├── classes.html │ ├── clipboard.js │ ├── closed.png │ ├── cookie.js │ ├── crc_8hpp_source.html │ ├── deprecated.html │ ├── dir_5c4711b76244cf820e6fc766a3eae98f.html │ ├── dir_68267d1309a1af8e8297ef4c3efbcdba.html │ ├── dir_89deb882b528f943e97271a20701dad4.html │ ├── dir_bce4fe468017adc58bf81882531ea016.html │ ├── dir_d44c64559bbebec7f509842c48db8b23.html │ ├── dir_f8aebf652183de33714d471cbd098255.html │ ├── dir_fa17a7b3bf7c731ce009520520ae23a8.html │ ├── doc.png │ ├── doc.svg │ ├── docd.svg │ ├── doxygen.css │ ├── doxygen.svg │ ├── doxygen_crawl.html │ ├── dynsections.js │ ├── files.html │ ├── folderclosed.png │ ├── folderclosed.svg │ ├── folderclosedd.svg │ ├── folderopen.png │ ├── folderopen.svg │ ├── folderopend.svg │ ├── functions.html │ ├── functions_func.html │ ├── group__MB.html │ ├── hierarchy.html │ ├── index.html │ ├── jquery.js │ ├── menu.js │ ├── menudata.js │ ├── minus.svg │ ├── minusd.svg │ ├── modbusCell_8hpp_source.html │ ├── modbusException_8hpp_source.html │ ├── modbusRequest_8hpp_source.html │ ├── modbusResponse_8hpp_source.html │ ├── modbusUtils_8hpp_source.html │ ├── modules.html │ ├── namespaceMB.html │ ├── namespaceMB_1_1CRC.html │ ├── namespaceMB_1_1utils.html │ ├── namespacemembers.html │ ├── namespacemembers_enum.html │ ├── namespacemembers_func.html │ ├── namespaces.html │ ├── nav_f.png │ ├── nav_fd.png │ ├── nav_g.png │ ├── nav_h.png │ ├── nav_hd.png │ ├── open.png │ ├── pages.html │ ├── plus.svg │ ├── plusd.svg │ ├── search │ ├── all_0.html │ ├── all_0.js │ ├── all_1.html │ ├── all_1.js │ ├── all_10.js │ ├── all_11.js │ ├── all_2.html │ ├── all_2.js │ ├── all_3.html │ ├── all_3.js │ ├── all_4.html │ ├── all_4.js │ ├── all_5.html │ ├── all_5.js │ ├── all_6.html │ ├── all_6.js │ ├── all_7.html │ ├── all_7.js │ ├── all_8.html │ ├── all_8.js │ ├── all_9.html │ ├── all_9.js │ ├── all_a.js │ ├── all_b.js │ ├── all_c.js │ ├── all_d.js │ ├── all_e.js │ ├── all_f.js │ ├── classes_0.html │ ├── classes_0.js │ ├── classes_1.html │ ├── classes_1.js │ ├── classes_2.html │ ├── classes_2.js │ ├── close.svg │ ├── enums_0.html │ ├── enums_0.js │ ├── functions_0.html │ ├── functions_0.js │ ├── functions_1.html │ ├── functions_1.js │ ├── functions_2.html │ ├── functions_2.js │ ├── functions_3.html │ ├── functions_3.js │ ├── functions_4.html │ ├── functions_4.js │ ├── functions_5.html │ ├── functions_5.js │ ├── functions_6.html │ ├── functions_6.js │ ├── functions_7.html │ ├── functions_7.js │ ├── functions_8.html │ ├── functions_8.js │ ├── functions_9.html │ ├── functions_9.js │ ├── functions_a.js │ ├── mag.svg │ ├── mag_d.svg │ ├── mag_sel.svg │ ├── mag_seld.svg │ ├── namespaces_0.html │ ├── namespaces_0.js │ ├── nomatches.html │ ├── pages_0.js │ ├── pages_1.js │ ├── pages_2.js │ ├── pages_3.js │ ├── search.css │ ├── search.js │ ├── search_l.png │ ├── search_m.png │ ├── search_r.png │ └── searchdata.js │ ├── server_8hpp_source.html │ ├── splitbar.png │ ├── splitbard.png │ ├── sync_off.png │ ├── sync_on.png │ ├── tab_a.png │ ├── tab_ad.png │ ├── tab_b.png │ ├── tab_bd.png │ ├── tab_h.png │ ├── tab_hd.png │ ├── tab_s.png │ ├── tab_sd.png │ └── tabs.css ├── example └── main.cpp ├── include └── MB │ ├── Serial │ └── connection.hpp │ ├── TCP │ ├── connection.hpp │ └── server.hpp │ ├── crc.hpp │ ├── modbusCell.hpp │ ├── modbusException.hpp │ ├── modbusRequest.hpp │ ├── modbusResponse.hpp │ └── modbusUtils.hpp ├── reformat-all.sh ├── shell.nix ├── src ├── CMakeLists.txt ├── Serial │ ├── CMakeLists.txt │ └── connection.cpp ├── TCP │ ├── CMakeLists.txt │ ├── connection.cpp │ └── server.cpp ├── crc.cpp ├── modbusException.cpp ├── modbusRequest.cpp └── modbusResponse.cpp └── tests ├── CMakeLists.txt ├── MB ├── ModbusCellTests.cpp ├── ModbusExceptionTests.cpp ├── ModbusFunctionalTests.cpp ├── ModbusRequestTests.cpp └── ModbusResponseTests.cpp └── main.cpp /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: Clang formatting checker 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | pull_request: 7 | branches: ["master"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | container: 13 | image: silkeh/clang # https://hub.docker.com/r/silkeh/clang 14 | env: 15 | DRY: "TRUE" 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 1 21 | 22 | - name: Checking formatting 23 | run: DRY=TRUE bash reformat-all.sh 24 | -------------------------------------------------------------------------------- /.github/workflows/cmake-multi-platform.yml: -------------------------------------------------------------------------------- 1 | name: CMake on multiple platforms 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | pull_request: 7 | branches: ["master"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ${{ matrix.os }} 12 | 13 | strategy: 14 | # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. 15 | fail-fast: false 16 | 17 | # Currently supported: 18 | # - Linux + GCC 19 | # - Linux + CLANG 20 | # Planned: 21 | # - Windows + CL 22 | matrix: 23 | os: [ubuntu-latest, windows-latest] 24 | build_type: [Release] 25 | c_compiler: [gcc, clang, cl] 26 | include: 27 | - os: ubuntu-latest 28 | c_compiler: gcc 29 | cpp_compiler: g++ 30 | - os: ubuntu-latest 31 | c_compiler: clang 32 | cpp_compiler: clang++ 33 | - os: windows-latest 34 | c_compiler: cl 35 | cpp_compiler: cl 36 | exclude: 37 | - os: windows-latest 38 | c_compiler: gcc 39 | - os: windows-latest 40 | c_compiler: clang 41 | - os: ubuntu-latest 42 | c_compiler: cl 43 | 44 | steps: 45 | - uses: actions/checkout@v4 46 | with: 47 | submodules: "recursive" 48 | fetch-depth: 1 49 | 50 | # Dependecies needed only for Linux - Modbus Communication 51 | - name: Install dependencies 52 | run: | 53 | sudo apt-get update 54 | sudo apt-get install -y libnet1-dev 55 | if: matrix.os == 'ubuntu-latest' 56 | 57 | - name: Set reusable strings 58 | id: strings 59 | shell: bash 60 | run: | 61 | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" 62 | 63 | - name: Configure CMake 64 | run: > 65 | cmake -B ${{ steps.strings.outputs.build-output-dir }} 66 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} 67 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} 68 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} 69 | -DMODBUS_EXAMPLE=ON 70 | -DMODBUS_TESTS=ON 71 | -DMODBUS_TCP_COMMUNICATION=${{ matrix.os == 'windows-latest' && 'OFF' || matrix.os == 'ubuntu-latest' && 'ON' }} 72 | -DMODBUS_SERIAL_COMMUNICATION=${{ matrix.os == 'windows-latest' && 'OFF' || matrix.os == 'ubuntu-latest' && 'ON' }} 73 | -S ${{ github.workspace }} 74 | 75 | - name: Build 76 | run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} 77 | 78 | - name: Test 79 | run: ${{ steps.strings.outputs.build-output-dir }}/${{ matrix.os == 'windows-latest' && 'tests\Release\Google_Tests_run.exe' || matrix.os == 'ubuntu-latest' && '/tests/Google_Tests_run' }} 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | build 34 | 35 | # Windows specific 36 | out 37 | .vs 38 | 39 | # Gtags 40 | GTAGS 41 | GRTAGS 42 | GPATH 43 | 44 | # Clangd 45 | compile_commands.json 46 | .clang_complete 47 | .cache 48 | .clangd 49 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests/googletest"] 2 | path = tests/googletest 3 | url = https://github.com/google/googletest 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(modbus) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | if (MSVC) 7 | add_compile_options(/W3 /MT) 8 | # Otherwise, MSVC complains about strncopy 9 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 10 | else() 11 | add_compile_options(-Wall -Wextra -Werror -pedantic) 12 | endif() 13 | 14 | option(MODBUS_EXAMPLE "Build example program" OFF) 15 | option(MODBUS_TESTS "Build tests" OFF) 16 | option(MODBUS_TCP_COMMUNICATION "Use Modbus TCP communication library" ON) 17 | 18 | if(NOT win32) 19 | # Serial not supported on Windows 20 | option(MODBUS_SERIAL_COMMUNICATION "Use Modbus serial communication library" OFF) # not supported by windows platform 21 | else() 22 | message(STATUS "Modbus Serial not supported on Windows.") 23 | endif() 24 | 25 | add_subdirectory(src) 26 | 27 | if(MODBUS_TESTS) 28 | add_subdirectory(tests) 29 | endif() 30 | 31 | if(MODBUS_EXAMPLE) 32 | add_executable(ex example/main.cpp) 33 | target_link_libraries(ex PUBLIC Modbus_Core) 34 | endif() 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mazurel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Modbus library for modern C++

2 | 3 | [![CMake on multiple platforms](https://github.com/Mazurel/Modbus/actions/workflows/cmake-multi-platform.yml/badge.svg?branch=master)](https://github.com/Mazurel/Modbus/actions/workflows/cmake-multi-platform.yml) 4 | [![Clang formatting checker](https://github.com/Mazurel/Modbus/actions/workflows/clang-format.yml/badge.svg?branch=master)](https://github.com/Mazurel/Modbus/actions/workflows/clang-format.yml) 5 | 6 | 7 | Library for high level Modbus frame/packet manipulation, including encoding and decoding, all written in modern C++17. 8 | 9 | Additionally, library contains reference TCP and RTU implementation (on Linux only !), 10 | that you can use as a starting point for you application ! 11 | Until there will some reliable way to test it, it will be treated as such. 12 | 13 |
14 | 15 | More informations for Windows users 16 | 17 | If you are interested in Windows RTU implementation, you can look at to pull request: https://github.com/Mazurel/Modbus/pull/5 . 18 | I am currently unable to merge it, as I do not have required hardware for testing. 19 | 20 |
21 | 22 | 23 | # Table of content 24 | - [Why](#why) 25 | - [Important Concept](#important-concept) 26 | - [Possibilities](#possibilities) 27 | - [Dependencies](#dependencies) 28 | - [Status](#status) 29 | - [Installation](#how-to-install-it-) 30 | - [Api](#api) 31 | 32 | # Why 33 | 34 | When I was working on my last project and tried to find a good C++ Modbus library (other than Qt) I was unable to find it. 35 | That is why I have decided to share my own implementation of Modbus. 36 | 37 | # Important Concept 38 | 39 | This library is **mainly** for providing Modbus logic. 40 | It doesnt aim to have best communication implementation, as it is usually HW-specific. 41 | It gives user ability to create Modbus frames using high level api and convert them to raw bytes or show them as string. 42 | That is why *Modbus Core* is OS independent and can be easily used with other communication frameworks, 43 | assuming that you compiler supports at least C++17. 44 | 45 | Modbus communiaction module is **enabled** by default and works pretty well on linux. 46 | If you are using your own communication, be sure to disable it via cmake variable. 47 | 48 | # Possibilities 49 | 50 | Quick example of what Modbus Core can do: 51 | 52 | Code: 53 | 54 | ```c++ 55 | #include "MB/modbusException.hpp" 56 | #include "MB/modbusRequest.hpp" 57 | #include "MB/modbusResponse.hpp" 58 | 59 | // Create simple request 60 | MB::ModbusRequest request(1, MB::utils::ReadDiscreteOutputCoils, 100, 10); 61 | 62 | std::cout << "Stringed Request: " << request.toString() << std::endl; 63 | 64 | std::cout << "Raw request:" << std::endl; 65 | 66 | // Get raw represenatation for request 67 | std::vector rawed = request.toRaw(); 68 | 69 | // Method for showing byte 70 | auto showByte = [](const uint8_t &byte) { 71 | std::cout << " 0x" << std::hex << std::setw(2) << std::setfill('0') 72 | << static_cast(byte); 73 | }; 74 | 75 | // Show all bytes 76 | std::for_each(rawed.begin(), rawed.end(), showByte); 77 | std::cout << std::endl; 78 | 79 | // Create CRC and pointer to its bytes 80 | uint16_t CRC = MB::utils::calculateCRC(rawed); 81 | auto CRCptr = reinterpret_cast(&CRC); 82 | 83 | // Show byted CRC for request 84 | std::cout << "CRC for the above code: "; 85 | std::for_each(CRCptr, CRCptr + 2, showByte); 86 | std::cout << std::endl; 87 | 88 | auto request1 = MB::ModbusRequest::fromRaw(rawed); 89 | std::cout << "Stringed Request 1 after rawed: " << request1.toString() << std::endl; 90 | 91 | // Add CRC to the end of raw request so that it can be loaded with CRC check 92 | rawed.insert(rawed.end(), CRCptr, CRCptr + 2); 93 | auto request2 = MB::ModbusRequest::fromRawCRC(rawed); // Throws on invalid CRC 94 | std::cout << "Stringed Request 2 after rawed: " << request2.toString() << std::endl; 95 | ``` 96 | 97 | Output: 98 | ```bash 99 | Stringed Request: Read from output coils, from slave 1, starting from address 100, on 10 registers 100 | Raw request: 101 | 0x01 0x01 0x00 0x64 0x00 0x0a 102 | CRC for the above code: 0xfd 0xd2 103 | Stringed Request 1 after rawed: Read from output coils, from slave 1, starting from address 100, on 10 registers 104 | Stringed Request 2 after rawed: Read from output coils, from slave 1, starting from address 100, on 10 registers 105 | ``` 106 | 107 | # Dependencies 108 | 109 | Library core is dependency free - except for C++ standard library. 110 | 111 | For communication module, you may need: 112 | 113 | - libnet - only for tcp communication (not needed if communication is disabled) 114 | 115 | # STATUS 116 | 117 | Currently Modbus Core is fully functional and (I belive) it doesn't have any bugs. 118 | 119 | Modbus Communication is working *currently* only for linux, it works well on TCP and Serial (tested on raspberry pi). 120 | 121 | # How to learn Modbus ? 122 | 123 | Just use [Simply modbus](http://www.simplymodbus.ca/FAQ.htm). 124 | 125 | # How to install it ? 126 | 127 | ### Using CMAKE and git 128 | 129 | First go to directory that will contain this library. 130 | 131 | ```bash 132 | git clone https://github.com/Mazurel/Modbus 133 | git submodule update --init --recursive # Fetch submodules (google tests) 134 | ``` 135 | 136 | Then add to your CMakeLists.txt 137 | ```cmake 138 | add_subdirectory(Modbus) 139 | target_link_libraries( Modbus) 140 | ``` 141 | You should be able to use library. 142 | 143 | **NOTE** 144 | If you are on other os then gnu/linux you should disable communication part of modbus via cmake variable MODBUS_COMMUNICATION. 145 | 146 | # API 147 | 148 | API documentation is generated using [Doxygen](https://www.doxygen.nl) and it is available online under this [link](https://mazurel.github.io/docs/modbus/index.html). 149 | If you want, you can also generate it yourself ! 150 | -------------------------------------------------------------------------------- /docs/html/bc_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/bc_s.png -------------------------------------------------------------------------------- /docs/html/bc_sd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/bc_sd.png -------------------------------------------------------------------------------- /docs/html/bdwn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/bdwn.png -------------------------------------------------------------------------------- /docs/html/classMB_1_1ModbusException.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/classMB_1_1ModbusException.png -------------------------------------------------------------------------------- /docs/html/classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Class Index 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Class Index
75 |
76 |
77 |
C | M | S
78 |
79 |
80 |
C
81 |
Connection (MB::Serial)
Connection (MB::TCP)
82 |
83 |
M
84 |
ModbusCell (MB)
ModbusException (MB)
ModbusRequest (MB)
ModbusResponse (MB)
85 |
86 |
S
87 |
Server (MB::TCP)
88 |
89 |
90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/html/clipboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | The code below is based on the Doxygen Awesome project, see 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 - 2022 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | let clipboard_title = "Copy to clipboard" 31 | let clipboard_icon = `` 32 | let clipboard_successIcon = `` 33 | let clipboard_successDuration = 1000 34 | 35 | $(function() { 36 | if(navigator.clipboard) { 37 | const fragments = document.getElementsByClassName("fragment") 38 | for(const fragment of fragments) { 39 | const clipboard_div = document.createElement("div") 40 | clipboard_div.classList.add("clipboard") 41 | clipboard_div.innerHTML = clipboard_icon 42 | clipboard_div.title = clipboard_title 43 | $(clipboard_div).click(function() { 44 | const content = this.parentNode.cloneNode(true) 45 | // filter out line number and folded fragments from file listings 46 | content.querySelectorAll(".lineno, .ttc, .foldclosed").forEach((node) => { node.remove() }) 47 | let text = content.textContent 48 | // remove trailing newlines and trailing spaces from empty lines 49 | text = text.replace(/^\s*\n/gm,'\n').replace(/\n*$/,'') 50 | navigator.clipboard.writeText(text); 51 | this.classList.add("success") 52 | this.innerHTML = clipboard_successIcon 53 | window.setTimeout(() => { // switch back to normal icon after timeout 54 | this.classList.remove("success") 55 | this.innerHTML = clipboard_icon 56 | }, clipboard_successDuration); 57 | }) 58 | fragment.insertBefore(clipboard_div, fragment.firstChild) 59 | } 60 | } 61 | }) 62 | -------------------------------------------------------------------------------- /docs/html/closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/closed.png -------------------------------------------------------------------------------- /docs/html/cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Cookie helper functions 3 | Copyright (c) 2023 Dimitri van Heesch 4 | Released under MIT license. 5 | */ 6 | let Cookie = { 7 | cookie_namespace: 'doxygen_', 8 | 9 | readSetting(cookie,defVal) { 10 | if (window.chrome) { 11 | const val = localStorage.getItem(this.cookie_namespace+cookie) || 12 | sessionStorage.getItem(this.cookie_namespace+cookie); 13 | if (val) return val; 14 | } else { 15 | let myCookie = this.cookie_namespace+cookie+"="; 16 | if (document.cookie) { 17 | const index = document.cookie.indexOf(myCookie); 18 | if (index != -1) { 19 | const valStart = index + myCookie.length; 20 | let valEnd = document.cookie.indexOf(";", valStart); 21 | if (valEnd == -1) { 22 | valEnd = document.cookie.length; 23 | } 24 | return document.cookie.substring(valStart, valEnd); 25 | } 26 | } 27 | } 28 | return defVal; 29 | }, 30 | 31 | writeSetting(cookie,val,days=10*365) { // default days='forever', 0=session cookie, -1=delete 32 | if (window.chrome) { 33 | if (days==0) { 34 | sessionStorage.setItem(this.cookie_namespace+cookie,val); 35 | } else { 36 | localStorage.setItem(this.cookie_namespace+cookie,val); 37 | } 38 | } else { 39 | let date = new Date(); 40 | date.setTime(date.getTime()+(days*24*60*60*1000)); 41 | const expiration = days!=0 ? "expires="+date.toGMTString()+";" : ""; 42 | document.cookie = this.cookie_namespace + cookie + "=" + 43 | val + "; SameSite=Lax;" + expiration + "path=/"; 44 | } 45 | }, 46 | 47 | eraseSetting(cookie) { 48 | if (window.chrome) { 49 | if (localStorage.getItem(this.cookie_namespace+cookie)) { 50 | localStorage.removeItem(this.cookie_namespace+cookie); 51 | } else if (sessionStorage.getItem(this.cookie_namespace+cookie)) { 52 | sessionStorage.removeItem(this.cookie_namespace+cookie); 53 | } 54 | } else { 55 | this.writeSetting(cookie,'',-1); 56 | } 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /docs/html/deprecated.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Deprecated List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 |
73 |
74 |
Deprecated List
75 |
76 |
77 |
78 |
Member MB::utils::calculateCRC (const uint8_t *buff, size_t len)
79 |
Calculates CRC - please use functions from MB::CRC
80 |
Member MB::utils::calculateCRC (const std::vector< uint8_t > &buffer)
81 |
Calculates CRC - please use functions from MB::CRC
82 |
83 |
84 |
85 | 86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/html/dir_5c4711b76244cf820e6fc766a3eae98f.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: src/TCP Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
TCP Directory Reference
79 |
80 |
81 |
82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: src Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
src Directory Reference
79 |
80 |
81 | 82 | 84 | 85 | 86 | 87 | 88 |

83 | Directories

 Serial
 
 TCP
 
89 |
90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/html/dir_89deb882b528f943e97271a20701dad4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: include/MB/TCP Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
TCP Directory Reference
79 |
80 |
81 | 82 | 84 | 85 | 86 | 87 | 88 |

83 | Files

 connection.hpp
 
 server.hpp
 
89 |
90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/html/dir_bce4fe468017adc58bf81882531ea016.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: src/Serial Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
Serial Directory Reference
79 |
80 |
81 |
82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/html/dir_d44c64559bbebec7f509842c48db8b23.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: include Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
include Directory Reference
79 |
80 |
81 | 82 | 84 | 85 | 86 |

83 | Directories

 MB
 
87 |
88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/html/dir_fa17a7b3bf7c731ce009520520ae23a8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: include/MB/Serial Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 | 52 |
56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 |
Loading...
65 |
Searching...
66 |
No Matches
67 |
68 |
69 |
70 |
71 | 72 | 76 |
77 |
78 |
Serial Directory Reference
79 |
80 |
81 | 82 | 84 | 85 | 86 |

83 | Files

 connection.hpp
 
87 |
88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/html/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/doc.png -------------------------------------------------------------------------------- /docs/html/doc.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/html/docd.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/html/doxygen_crawl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Validator / crawler helper 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/html/folderclosed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/folderclosed.png -------------------------------------------------------------------------------- /docs/html/folderclosed.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/html/folderclosedd.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/html/folderopen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/folderopen.png -------------------------------------------------------------------------------- /docs/html/folderopen.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/html/folderopend.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/html/menudata.js: -------------------------------------------------------------------------------- 1 | /* 2 | @licstart The following is the entire license notice for the JavaScript code in this file. 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (C) 1997-2020 by Dimitri van Heesch 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 9 | and associated documentation files (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or 15 | substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | @licend The above is the entire license notice for the JavaScript code in this file 24 | */ 25 | var menudata={children:[ 26 | {text:"Main Page",url:"index.html"}, 27 | {text:"Related Pages",url:"pages.html"}, 28 | {text:"Namespaces",url:"namespaces.html",children:[ 29 | {text:"Namespace List",url:"namespaces.html"}, 30 | {text:"Namespace Members",url:"namespacemembers.html",children:[ 31 | {text:"All",url:"namespacemembers.html"}, 32 | {text:"Functions",url:"namespacemembers_func.html"}, 33 | {text:"Enumerations",url:"namespacemembers_enum.html"}]}]}, 34 | {text:"Classes",url:"annotated.html",children:[ 35 | {text:"Class List",url:"annotated.html"}, 36 | {text:"Class Index",url:"classes.html"}, 37 | {text:"Class Hierarchy",url:"hierarchy.html"}, 38 | {text:"Class Members",url:"functions.html",children:[ 39 | {text:"All",url:"functions.html",children:[ 40 | {text:"c",url:"functions.html#index_c"}, 41 | {text:"f",url:"functions.html#index_f"}, 42 | {text:"g",url:"functions.html#index_g"}, 43 | {text:"i",url:"functions.html#index_i"}, 44 | {text:"m",url:"functions.html#index_m"}, 45 | {text:"r",url:"functions.html#index_r"}, 46 | {text:"s",url:"functions.html#index_s"}, 47 | {text:"t",url:"functions.html#index_t"}, 48 | {text:"w",url:"functions.html#index_w"}]}, 49 | {text:"Functions",url:"functions_func.html",children:[ 50 | {text:"c",url:"functions_func.html#index_c"}, 51 | {text:"f",url:"functions_func.html#index_f"}, 52 | {text:"g",url:"functions_func.html#index_g"}, 53 | {text:"i",url:"functions_func.html#index_i"}, 54 | {text:"m",url:"functions_func.html#index_m"}, 55 | {text:"r",url:"functions_func.html#index_r"}, 56 | {text:"s",url:"functions_func.html#index_s"}, 57 | {text:"t",url:"functions_func.html#index_t"}, 58 | {text:"w",url:"functions_func.html#index_w"}]}]}]}, 59 | {text:"Files",url:"files.html",children:[ 60 | {text:"File List",url:"files.html"}]}]} 61 | -------------------------------------------------------------------------------- /docs/html/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/html/minusd.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/html/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Modules 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | 28 | 29 | 30 |
24 |
Modbus cpp 25 |  0.1 26 |
27 |
31 |
32 | 33 | 34 | 39 | 40 | 41 | 48 | 49 |
50 | 51 |
55 |
56 | 57 | 58 |
59 | 62 |
63 | 64 |
65 |
66 |
Modules
67 |
68 |
69 |
Here is a list of all modules:
70 | 71 | 72 |
 ::utils
73 |
74 |
75 | 76 |
79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/html/namespacemembers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Namespace Members 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Here is a list of all documented namespace members with links to the namespaces they belong to:
89 |
90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/html/namespacemembers_enum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Namespace Members 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Here is a list of all documented namespace enums with links to the namespaces they belong to:
80 |
81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/html/namespacemembers_func.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Namespace Members 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Here is a list of all documented namespace functions with links to the namespaces they belong to:
85 |
86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/html/namespaces.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Namespace List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Namespace List
75 |
76 |
77 |
Here is a list of all documented namespaces with brief descriptions:
78 |
[detail level 12]
79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
 NMB
 NCRCThis namespace contains functions used for CRC calculation
 Nutils
 CModbusCellClass that represents single modbus cell, it is either coil(bool) or reg(uint16_t)
 CModbusException
 CModbusRequest
 CModbusResponse
87 |
88 |
89 | 90 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /docs/html/nav_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/nav_f.png -------------------------------------------------------------------------------- /docs/html/nav_fd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/nav_fd.png -------------------------------------------------------------------------------- /docs/html/nav_g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/nav_g.png -------------------------------------------------------------------------------- /docs/html/nav_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/nav_h.png -------------------------------------------------------------------------------- /docs/html/nav_hd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/nav_hd.png -------------------------------------------------------------------------------- /docs/html/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/open.png -------------------------------------------------------------------------------- /docs/html/pages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modbus cpp: Related Pages 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 29 | 30 | 31 |
26 |
Modbus cpp 0.1 27 |
28 |
32 |
33 | 34 | 35 | 40 | 41 | 42 | 50 | 51 |
52 | 53 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
Loading...
66 |
Searching...
67 |
No Matches
68 |
69 |
70 |
71 |
72 | 73 |
74 |
Related Pages
75 |
76 |
77 |
Here is a list of all related documentation pages:
78 | 79 | 80 |
 Deprecated List
81 |
82 |
83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/html/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/html/plusd.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/html/search/all_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['and_20git_0',['Using CMAKE and git',['../index.html#autotoc_md8',1,'']]], 4 | ['api_1',['API',['../index.html#autotoc_md9',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['bigendianconv_0',['bigEndianConv',['../namespaceMB_1_1utils.html#a2057e90dfbefb2bc7cea23f6140d5a04',1,'MB::utils']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/all_10.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['what_0',['what',['../classMB_1_1ModbusException.html#a1af9903bea9caabdf35ad69ce17a682a',1,'MB::ModbusException']]], 4 | ['why_1',['Why',['../index.html#autotoc_md1',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_11.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['what_0',['what',['../classMB_1_1ModbusException.html#a1af9903bea9caabdf35ad69ce17a682a',1,'MB::ModbusException']]], 4 | ['why_1',['Why',['../index.html#autotoc_md1',1,'']]], 5 | ['wont_20be_20it_20is_20preffered_20to_20use_20doxygen_20for_20code_20documentation_2',['The below API is not finished (propably wont be), it is preffered to use doxygen for code documentation.',['../index.html#autotoc_md11',1,'']]] 6 | ]; 7 | -------------------------------------------------------------------------------- /docs/html/search/all_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['calculatecrc_0',['calculateCRC',['../namespaceMB_1_1CRC.html#a2a8e570461d56e3a269e2d1c242bcf2f',1,'MB::CRC::calculateCRC(const uint8_t *buff, std::size_t len)'],['../namespaceMB_1_1CRC.html#a2c9c245bb92560f18d3127961c3e2d5f',1,'MB::CRC::calculateCRC(const std::vector< uint8_t > &buffer)'],['../namespaceMB_1_1utils.html#aa419ed339bbdacd4108fb5cc1cd14539',1,'MB::utils::calculateCRC(const uint8_t *buff, size_t len)'],['../namespaceMB_1_1utils.html#a102e7bc4008a2658a5db76a9b70bec97',1,'MB::utils::calculateCRC(const std::vector< uint8_t > &buffer)']]], 4 | ['cmake_20and_20git_1',['Using CMAKE and git',['../index.html#autotoc_md8',1,'']]], 5 | ['coil_2',['coil',['../classMB_1_1ModbusCell.html#a8d0771f1c9b700dfd479c03f427fc195',1,'MB::ModbusCell::coil()'],['../classMB_1_1ModbusCell.html#a431d6e379b18657ddbb2a84fcd947f83',1,'MB::ModbusCell::coil() const']]], 6 | ['concept_3',['Important Concept',['../index.html#autotoc_md2',1,'']]], 7 | ['connection_4',['Connection',['../classMB_1_1Serial_1_1Connection.html',1,'MB::Serial::Connection'],['../classMB_1_1TCP_1_1Connection.html',1,'MB::TCP::Connection']]], 8 | ['content_5',['Table of content',['../index.html#autotoc_md0',1,'']]], 9 | ['cpp_6',['Modbus cpp',['../index.html',1,'']]] 10 | ]; 11 | -------------------------------------------------------------------------------- /docs/html/search/all_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_3.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['dependencies_0',['Dependencies',['../index.html#autotoc_md4',1,'']]], 4 | ['deprecated_20list_1',['Deprecated List',['../deprecated.html',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_4.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['from_0',['from',['../classMB_1_1ModbusResponse.html#a637d66a0504981767fc185f64f57059c',1,'MB::ModbusResponse']]], 4 | ['functionregister_1',['functionRegister',['../namespaceMB_1_1utils.html#ad967d0ef18fecbc1a231143db3793991',1,'MB::utils']]], 5 | ['functionregisters_2',['functionRegisters',['../classMB_1_1ModbusRequest.html#a8097a0866398cef7f1244ca7ca412062',1,'MB::ModbusRequest']]], 6 | ['functiontype_3',['functionType',['../classMB_1_1ModbusRequest.html#a22966d0c19bb79c4e8cf03edb5b74a4e',1,'MB::ModbusRequest::functionType()'],['../namespaceMB_1_1utils.html#ab24a81a029cf6c4765eab5d74b7d8dff',1,'MB::utils::functionType()']]] 7 | ]; 8 | -------------------------------------------------------------------------------- /docs/html/search/all_5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_5.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['geterrorcode_0',['getErrorCode',['../classMB_1_1ModbusException.html#a99b4583ae15c2a13530e3751e9ad2737',1,'MB::ModbusException']]], 4 | ['git_1',['Using CMAKE and git',['../index.html#autotoc_md8',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_6.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['how_20to_20install_20it_0',['How to install it ?',['../index.html#autotoc_md7',1,'']]], 4 | ['how_20to_20learn_20modbus_1',['How to learn Modbus ?',['../index.html#autotoc_md6',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_7.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['important_20concept_0',['Important Concept',['../index.html#autotoc_md2',1,'']]], 4 | ['initcoil_1',['initCoil',['../classMB_1_1ModbusCell.html#aa7aa19c9be4c990fc16fcde1c027e485',1,'MB::ModbusCell']]], 5 | ['initreg_2',['initReg',['../classMB_1_1ModbusCell.html#a890610419b58a1ec8f7e5cffa6a69d72',1,'MB::ModbusCell']]], 6 | ['install_20it_3',['How to install it ?',['../index.html#autotoc_md7',1,'']]], 7 | ['iscoil_4',['isCoil',['../classMB_1_1ModbusCell.html#a282399413ae7f24830680bbd46c8757b',1,'MB::ModbusCell']]], 8 | ['isreg_5',['isReg',['../classMB_1_1ModbusCell.html#a517c883a6008a6df97aeed57fdbb9126',1,'MB::ModbusCell']]], 9 | ['isslavevalid_6',['isSlaveValid',['../classMB_1_1ModbusException.html#a2d93520088d9adac402b4558a7441d80',1,'MB::ModbusException']]], 10 | ['isstandarderrorcode_7',['isStandardErrorCode',['../namespaceMB_1_1utils.html#a7aa22230ea192f06612fbc809fca2335',1,'MB::utils']]], 11 | ['it_8',['How to install it ?',['../index.html#autotoc_md7',1,'']]] 12 | ]; 13 | -------------------------------------------------------------------------------- /docs/html/search/all_8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_8.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['learn_20modbus_0',['How to learn Modbus ?',['../index.html#autotoc_md6',1,'']]], 4 | ['list_1',['Deprecated List',['../deprecated.html',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/all_9.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['mb_0',['MB',['../namespaceMB.html',1,'']]], 4 | ['mb_3a_3acrc_1',['CRC',['../namespaceMB_1_1CRC.html',1,'MB']]], 5 | ['mb_3a_3autils_2',['utils',['../namespaceMB_1_1utils.html',1,'MB']]], 6 | ['mberrorcode_3',['MBErrorCode',['../namespaceMB_1_1utils.html#aa34c557c9bf4c6bfeb86aa16b398de55',1,'MB::utils']]], 7 | ['mberrorcodetostr_4',['mbErrorCodeToStr',['../namespaceMB_1_1utils.html#af467d314367c209ef830b2ae97393b6f',1,'MB::utils']]], 8 | ['mbfunctioncode_5',['MBFunctionCode',['../namespaceMB_1_1utils.html#aa8ebb89b73bf4d0e3485b6341a50f116',1,'MB::utils']]], 9 | ['mbfunctionregisters_6',['MBFunctionRegisters',['../namespaceMB_1_1utils.html#a8098c5bcb6c33b219bafdee42334e260',1,'MB::utils']]], 10 | ['mbfunctiontostr_7',['mbFunctionToStr',['../namespaceMB_1_1utils.html#aaf546a5a9bb27ee4f7300064d18d9a9e',1,'MB::utils']]], 11 | ['mbfunctiontype_8',['MBFunctionType',['../namespaceMB_1_1utils.html#a0b3590994f5ba26cd61929f5a394ab70',1,'MB::utils']]], 12 | ['modbus_9',['How to learn Modbus ?',['../index.html#autotoc_md6',1,'']]], 13 | ['modbus_20cpp_10',['Modbus cpp',['../index.html',1,'']]], 14 | ['modbuscell_11',['ModbusCell',['../classMB_1_1ModbusCell.html',1,'MB::ModbusCell'],['../classMB_1_1ModbusCell.html#a588cd97494ca74c1d29b6ea55244fbb1',1,'MB::ModbusCell::ModbusCell()=default'],['../classMB_1_1ModbusCell.html#ae3b93fcff68e87b0e5dcc93a3359e588',1,'MB::ModbusCell::ModbusCell(uint16_t reg)'],['../classMB_1_1ModbusCell.html#a2ad10000cb33be94ab32fe60b20a4913',1,'MB::ModbusCell::ModbusCell(bool coil)']]], 15 | ['modbusexception_12',['ModbusException',['../classMB_1_1ModbusException.html',1,'MB::ModbusException'],['../classMB_1_1ModbusException.html#a27fc098093dfa4b7ff49acebb5c4a0bf',1,'MB::ModbusException::ModbusException(const std::vector< uint8_t > &inputData, bool CRC=false) noexcept'],['../classMB_1_1ModbusException.html#a2c60c1d081060a266a3f868698a289b6',1,'MB::ModbusException::ModbusException(utils::MBErrorCode errorCode, uint8_t slaveId=0xFF, utils::MBFunctionCode functionCode=utils::Undefined) noexcept']]], 16 | ['modbusrequest_13',['ModbusRequest',['../classMB_1_1ModbusRequest.html',1,'MB::ModbusRequest'],['../classMB_1_1ModbusRequest.html#af3bab6bbf1cc4f57f683878444e09a26',1,'MB::ModbusRequest::ModbusRequest(const std::vector< uint8_t > &inputData, bool CRC=false) noexcept(false)'],['../classMB_1_1ModbusRequest.html#a9d17929ef7908eb3c36df6d4d1c9b2c6',1,'MB::ModbusRequest::ModbusRequest(uint8_t slaveId=0, utils::MBFunctionCode functionCode=static_cast< utils::MBFunctionCode >(0), uint16_t address=0, uint16_t registersNumber=0, std::vector< ModbusCell > values={}) noexcept']]], 17 | ['modbusresponse_14',['ModbusResponse',['../classMB_1_1ModbusResponse.html',1,'MB::ModbusResponse'],['../classMB_1_1ModbusResponse.html#abb81c341259007fffa42f59d5a3bdf6d',1,'MB::ModbusResponse::ModbusResponse(std::vector< uint8_t > inputData, bool CRC=false)'],['../classMB_1_1ModbusResponse.html#ad6c5eb8384de27b7b7211d69a7629f50',1,'MB::ModbusResponse::ModbusResponse(uint8_t slaveId=0, utils::MBFunctionCode functionCode=static_cast< utils::MBFunctionCode >(0), uint16_t address=0, uint16_t registersNumber=0, std::vector< ModbusCell > values={})']]] 18 | ]; 19 | -------------------------------------------------------------------------------- /docs/html/search/all_a.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['of_20content_0',['Table of content',['../index.html#autotoc_md0',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/all_b.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['possibilities_0',['Possibilities',['../index.html#autotoc_md3',1,'']]], 4 | ['pushuint16_1',['pushUint16',['../namespaceMB_1_1utils.html#a7f0598129d992fb13a6239874f051918',1,'MB::utils']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/all_c.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['reg_0',['reg',['../classMB_1_1ModbusCell.html#a2637cd2e9111044a55f512586fbbead4',1,'MB::ModbusCell::reg()'],['../classMB_1_1ModbusCell.html#abdc97b32e6c9c45bbb5f4a94a879333f',1,'MB::ModbusCell::reg() const']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/all_d.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['send_0',['send',['../classMB_1_1Serial_1_1Connection.html#a1df3d9e4323cfc0bf4f1a54c3fd07ee8',1,'MB::Serial::Connection']]], 4 | ['server_1',['Server',['../classMB_1_1TCP_1_1Server.html',1,'MB::TCP']]], 5 | ['setslaveid_2',['setSlaveID',['../classMB_1_1ModbusException.html#a344445f1b157f5e5d66946cd893c72fd',1,'MB::ModbusException']]], 6 | ['splituint16_3',['splitUint16',['../namespaceMB_1_1utils.html#a370eb8cec7aed7dedd555c231fe46094',1,'MB::utils']]], 7 | ['status_4',['STATUS',['../index.html#autotoc_md5',1,'']]] 8 | ]; 9 | -------------------------------------------------------------------------------- /docs/html/search/all_e.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['table_20of_20content_0',['Table of content',['../index.html#autotoc_md0',1,'']]], 4 | ['to_20install_20it_1',['How to install it ?',['../index.html#autotoc_md7',1,'']]], 5 | ['to_20learn_20modbus_2',['How to learn Modbus ?',['../index.html#autotoc_md6',1,'']]], 6 | ['toraw_3',['toRaw',['../classMB_1_1ModbusException.html#a3f288bfe0b2b0f646ab0019faae78142',1,'MB::ModbusException::toRaw()'],['../classMB_1_1ModbusRequest.html#a869361ddbd05931ca0dbcebe688b0cb3',1,'MB::ModbusRequest::toRaw()']]], 7 | ['tostring_4',['toString',['../classMB_1_1ModbusCell.html#ab1af80c9aa58f7d02d79cb5fe6085c62',1,'MB::ModbusCell::toString()'],['../classMB_1_1ModbusException.html#a29d776e7ae321fbeba28a25df5159c79',1,'MB::ModbusException::toString()'],['../classMB_1_1ModbusRequest.html#a6d08428234559ffb96e5ef956b859442',1,'MB::ModbusRequest::toString()'],['../classMB_1_1ModbusResponse.html#ac5ff14306fc2b4886241602e6cdfd12e',1,'MB::ModbusResponse::toString()']]] 8 | ]; 9 | -------------------------------------------------------------------------------- /docs/html/search/all_f.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['using_20cmake_20and_20git_0',['Using CMAKE and git',['../index.html#autotoc_md8',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/classes_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/classes_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['connection_0',['Connection',['../classMB_1_1Serial_1_1Connection.html',1,'MB::Serial::Connection'],['../classMB_1_1TCP_1_1Connection.html',1,'MB::TCP::Connection']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/classes_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/classes_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['modbuscell_0',['ModbusCell',['../classMB_1_1ModbusCell.html',1,'MB']]], 4 | ['modbusexception_1',['ModbusException',['../classMB_1_1ModbusException.html',1,'MB']]], 5 | ['modbusrequest_2',['ModbusRequest',['../classMB_1_1ModbusRequest.html',1,'MB']]], 6 | ['modbusresponse_3',['ModbusResponse',['../classMB_1_1ModbusResponse.html',1,'MB']]] 7 | ]; 8 | -------------------------------------------------------------------------------- /docs/html/search/classes_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/classes_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['server_0',['Server',['../classMB_1_1TCP_1_1Server.html',1,'MB::TCP']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 12 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /docs/html/search/enums_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/enums_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['mberrorcode_0',['MBErrorCode',['../namespaceMB_1_1utils.html#aa34c557c9bf4c6bfeb86aa16b398de55',1,'MB::utils']]], 4 | ['mbfunctioncode_1',['MBFunctionCode',['../namespaceMB_1_1utils.html#aa8ebb89b73bf4d0e3485b6341a50f116',1,'MB::utils']]], 5 | ['mbfunctionregisters_2',['MBFunctionRegisters',['../namespaceMB_1_1utils.html#a8098c5bcb6c33b219bafdee42334e260',1,'MB::utils']]], 6 | ['mbfunctiontype_3',['MBFunctionType',['../namespaceMB_1_1utils.html#a0b3590994f5ba26cd61929f5a394ab70',1,'MB::utils']]] 7 | ]; 8 | -------------------------------------------------------------------------------- /docs/html/search/functions_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['bigendianconv_0',['bigEndianConv',['../namespaceMB_1_1utils.html#a2057e90dfbefb2bc7cea23f6140d5a04',1,'MB::utils']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/functions_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['calculatecrc_0',['calculateCRC',['../namespaceMB_1_1CRC.html#a2a8e570461d56e3a269e2d1c242bcf2f',1,'MB::CRC::calculateCRC(const uint8_t *buff, std::size_t len)'],['../namespaceMB_1_1CRC.html#a2c9c245bb92560f18d3127961c3e2d5f',1,'MB::CRC::calculateCRC(const std::vector< uint8_t > &buffer)'],['../namespaceMB_1_1utils.html#aa419ed339bbdacd4108fb5cc1cd14539',1,'MB::utils::calculateCRC(const uint8_t *buff, size_t len)'],['../namespaceMB_1_1utils.html#a102e7bc4008a2658a5db76a9b70bec97',1,'MB::utils::calculateCRC(const std::vector< uint8_t > &buffer)']]], 4 | ['coil_1',['coil',['../classMB_1_1ModbusCell.html#a8d0771f1c9b700dfd479c03f427fc195',1,'MB::ModbusCell::coil()'],['../classMB_1_1ModbusCell.html#a431d6e379b18657ddbb2a84fcd947f83',1,'MB::ModbusCell::coil() const']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/functions_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['from_0',['from',['../classMB_1_1ModbusResponse.html#a637d66a0504981767fc185f64f57059c',1,'MB::ModbusResponse']]], 4 | ['functionregister_1',['functionRegister',['../namespaceMB_1_1utils.html#ad967d0ef18fecbc1a231143db3793991',1,'MB::utils']]], 5 | ['functionregisters_2',['functionRegisters',['../classMB_1_1ModbusRequest.html#a8097a0866398cef7f1244ca7ca412062',1,'MB::ModbusRequest']]], 6 | ['functiontype_3',['functionType',['../classMB_1_1ModbusRequest.html#a22966d0c19bb79c4e8cf03edb5b74a4e',1,'MB::ModbusRequest::functionType()'],['../namespaceMB_1_1utils.html#ab24a81a029cf6c4765eab5d74b7d8dff',1,'MB::utils::functionType()']]] 7 | ]; 8 | -------------------------------------------------------------------------------- /docs/html/search/functions_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_3.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['geterrorcode_0',['getErrorCode',['../classMB_1_1ModbusException.html#a99b4583ae15c2a13530e3751e9ad2737',1,'MB::ModbusException']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/functions_4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_4.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['initcoil_0',['initCoil',['../classMB_1_1ModbusCell.html#aa7aa19c9be4c990fc16fcde1c027e485',1,'MB::ModbusCell']]], 4 | ['initreg_1',['initReg',['../classMB_1_1ModbusCell.html#a890610419b58a1ec8f7e5cffa6a69d72',1,'MB::ModbusCell']]], 5 | ['iscoil_2',['isCoil',['../classMB_1_1ModbusCell.html#a282399413ae7f24830680bbd46c8757b',1,'MB::ModbusCell']]], 6 | ['isreg_3',['isReg',['../classMB_1_1ModbusCell.html#a517c883a6008a6df97aeed57fdbb9126',1,'MB::ModbusCell']]], 7 | ['isslavevalid_4',['isSlaveValid',['../classMB_1_1ModbusException.html#a2d93520088d9adac402b4558a7441d80',1,'MB::ModbusException']]], 8 | ['isstandarderrorcode_5',['isStandardErrorCode',['../namespaceMB_1_1utils.html#a7aa22230ea192f06612fbc809fca2335',1,'MB::utils']]] 9 | ]; 10 | -------------------------------------------------------------------------------- /docs/html/search/functions_5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_5.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['mberrorcodetostr_0',['mbErrorCodeToStr',['../namespaceMB_1_1utils.html#af467d314367c209ef830b2ae97393b6f',1,'MB::utils']]], 4 | ['mbfunctiontostr_1',['mbFunctionToStr',['../namespaceMB_1_1utils.html#aaf546a5a9bb27ee4f7300064d18d9a9e',1,'MB::utils']]], 5 | ['modbuscell_2',['ModbusCell',['../classMB_1_1ModbusCell.html#a588cd97494ca74c1d29b6ea55244fbb1',1,'MB::ModbusCell::ModbusCell()=default'],['../classMB_1_1ModbusCell.html#ae3b93fcff68e87b0e5dcc93a3359e588',1,'MB::ModbusCell::ModbusCell(uint16_t reg)'],['../classMB_1_1ModbusCell.html#a2ad10000cb33be94ab32fe60b20a4913',1,'MB::ModbusCell::ModbusCell(bool coil)']]], 6 | ['modbusexception_3',['ModbusException',['../classMB_1_1ModbusException.html#a27fc098093dfa4b7ff49acebb5c4a0bf',1,'MB::ModbusException::ModbusException(const std::vector< uint8_t > &inputData, bool CRC=false) noexcept'],['../classMB_1_1ModbusException.html#a2c60c1d081060a266a3f868698a289b6',1,'MB::ModbusException::ModbusException(utils::MBErrorCode errorCode, uint8_t slaveId=0xFF, utils::MBFunctionCode functionCode=utils::Undefined) noexcept']]], 7 | ['modbusrequest_4',['ModbusRequest',['../classMB_1_1ModbusRequest.html#af3bab6bbf1cc4f57f683878444e09a26',1,'MB::ModbusRequest::ModbusRequest(const std::vector< uint8_t > &inputData, bool CRC=false) noexcept(false)'],['../classMB_1_1ModbusRequest.html#a9d17929ef7908eb3c36df6d4d1c9b2c6',1,'MB::ModbusRequest::ModbusRequest(uint8_t slaveId=0, utils::MBFunctionCode functionCode=static_cast< utils::MBFunctionCode >(0), uint16_t address=0, uint16_t registersNumber=0, std::vector< ModbusCell > values={}) noexcept']]], 8 | ['modbusresponse_5',['ModbusResponse',['../classMB_1_1ModbusResponse.html#abb81c341259007fffa42f59d5a3bdf6d',1,'MB::ModbusResponse::ModbusResponse(std::vector< uint8_t > inputData, bool CRC=false)'],['../classMB_1_1ModbusResponse.html#ad6c5eb8384de27b7b7211d69a7629f50',1,'MB::ModbusResponse::ModbusResponse(uint8_t slaveId=0, utils::MBFunctionCode functionCode=static_cast< utils::MBFunctionCode >(0), uint16_t address=0, uint16_t registersNumber=0, std::vector< ModbusCell > values={})']]] 9 | ]; 10 | -------------------------------------------------------------------------------- /docs/html/search/functions_6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_6.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['pushuint16_0',['pushUint16',['../namespaceMB_1_1utils.html#a7f0598129d992fb13a6239874f051918',1,'MB::utils']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/functions_7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_7.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['reg_0',['reg',['../classMB_1_1ModbusCell.html#a2637cd2e9111044a55f512586fbbead4',1,'MB::ModbusCell::reg()'],['../classMB_1_1ModbusCell.html#abdc97b32e6c9c45bbb5f4a94a879333f',1,'MB::ModbusCell::reg() const']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/functions_8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_8.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['send_0',['send',['../classMB_1_1Serial_1_1Connection.html#a1df3d9e4323cfc0bf4f1a54c3fd07ee8',1,'MB::Serial::Connection']]], 4 | ['setslaveid_1',['setSlaveID',['../classMB_1_1ModbusException.html#a344445f1b157f5e5d66946cd893c72fd',1,'MB::ModbusException']]], 5 | ['splituint16_2',['splitUint16',['../namespaceMB_1_1utils.html#a370eb8cec7aed7dedd555c231fe46094',1,'MB::utils']]] 6 | ]; 7 | -------------------------------------------------------------------------------- /docs/html/search/functions_9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/functions_9.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['toraw_0',['toRaw',['../classMB_1_1ModbusException.html#a3f288bfe0b2b0f646ab0019faae78142',1,'MB::ModbusException::toRaw()'],['../classMB_1_1ModbusRequest.html#a869361ddbd05931ca0dbcebe688b0cb3',1,'MB::ModbusRequest::toRaw()']]], 4 | ['tostring_1',['toString',['../classMB_1_1ModbusCell.html#ab1af80c9aa58f7d02d79cb5fe6085c62',1,'MB::ModbusCell::toString()'],['../classMB_1_1ModbusException.html#a29d776e7ae321fbeba28a25df5159c79',1,'MB::ModbusException::toString()'],['../classMB_1_1ModbusRequest.html#a6d08428234559ffb96e5ef956b859442',1,'MB::ModbusRequest::toString()'],['../classMB_1_1ModbusResponse.html#ac5ff14306fc2b4886241602e6cdfd12e',1,'MB::ModbusResponse::toString()']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/html/search/functions_a.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['what_0',['what',['../classMB_1_1ModbusException.html#a1af9903bea9caabdf35ad69ce17a682a',1,'MB::ModbusException']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/mag.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 12 | 14 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /docs/html/search/mag_d.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 12 | 14 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /docs/html/search/mag_sel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 13 | 15 | 21 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /docs/html/search/mag_seld.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 13 | 15 | 21 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /docs/html/search/namespaces_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
Loading...
12 |
13 | 18 |
Searching...
19 |
No Matches
20 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/html/search/namespaces_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['mb_0',['MB',['../namespaceMB.html',1,'']]], 4 | ['mb_3a_3acrc_1',['CRC',['../namespaceMB_1_1CRC.html',1,'MB']]], 5 | ['mb_3a_3autils_2',['utils',['../namespaceMB_1_1utils.html',1,'MB']]] 6 | ]; 7 | -------------------------------------------------------------------------------- /docs/html/search/nomatches.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
No Matches
10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/html/search/pages_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['cpp_0',['Modbus cpp',['../index.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/pages_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['deprecated_20list_0',['Deprecated List',['../deprecated.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/pages_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['list_0',['Deprecated List',['../deprecated.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/pages_3.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['modbus_20cpp_0',['Modbus cpp',['../index.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /docs/html/search/search_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/search/search_l.png -------------------------------------------------------------------------------- /docs/html/search/search_m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/search/search_m.png -------------------------------------------------------------------------------- /docs/html/search/search_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/search/search_r.png -------------------------------------------------------------------------------- /docs/html/search/searchdata.js: -------------------------------------------------------------------------------- 1 | var indexSectionsWithContent = 2 | { 3 | 0: "abcdfghilmoprstuw", 4 | 1: "cms", 5 | 2: "m", 6 | 3: "bcfgimprstw", 7 | 4: "m", 8 | 5: "cdlm" 9 | }; 10 | 11 | var indexSectionNames = 12 | { 13 | 0: "all", 14 | 1: "classes", 15 | 2: "namespaces", 16 | 3: "functions", 17 | 4: "enums", 18 | 5: "pages" 19 | }; 20 | 21 | var indexSectionLabels = 22 | { 23 | 0: "All", 24 | 1: "Classes", 25 | 2: "Namespaces", 26 | 3: "Functions", 27 | 4: "Enumerations", 28 | 5: "Pages" 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /docs/html/splitbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/splitbar.png -------------------------------------------------------------------------------- /docs/html/splitbard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/splitbard.png -------------------------------------------------------------------------------- /docs/html/sync_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/sync_off.png -------------------------------------------------------------------------------- /docs/html/sync_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/sync_on.png -------------------------------------------------------------------------------- /docs/html/tab_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_a.png -------------------------------------------------------------------------------- /docs/html/tab_ad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_ad.png -------------------------------------------------------------------------------- /docs/html/tab_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_b.png -------------------------------------------------------------------------------- /docs/html/tab_bd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_bd.png -------------------------------------------------------------------------------- /docs/html/tab_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_h.png -------------------------------------------------------------------------------- /docs/html/tab_hd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_hd.png -------------------------------------------------------------------------------- /docs/html/tab_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_s.png -------------------------------------------------------------------------------- /docs/html/tab_sd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mazurel/Modbus/17f7634fe9cd5a6ebca564bab72fea32fe6e56cd/docs/html/tab_sd.png -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "MB/modbusException.hpp" 6 | #include "MB/modbusRequest.hpp" 7 | #include "MB/modbusResponse.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void createRequest() { 14 | // Create simple request 15 | MB::ModbusRequest request(1, MB::utils::ReadDiscreteOutputCoils, 100, 10); 16 | 17 | std::cout << "Stringed Request: " << request.toString() << std::endl; 18 | 19 | std::cout << "Raw request:" << std::endl; 20 | 21 | // Get raw represenatation for request 22 | std::vector rawed = request.toRaw(); 23 | 24 | // Method for showing byte 25 | auto showByte = [](const uint8_t &byte) { 26 | std::cout << " 0x" << std::hex << std::setw(2) << std::setfill('0') 27 | << static_cast(byte); 28 | }; 29 | 30 | // Show all bytes 31 | std::for_each(rawed.begin(), rawed.end(), showByte); 32 | std::cout << std::endl; 33 | 34 | // Create CRC and pointer to its bytes 35 | uint16_t CRC = MB::utils::calculateCRC(rawed); 36 | auto CRCptr = reinterpret_cast(&CRC); 37 | 38 | // Show byted CRC for request 39 | std::cout << "CRC for the above code: "; 40 | std::for_each(CRCptr, CRCptr + 2, showByte); 41 | std::cout << std::endl; 42 | 43 | auto request1 = MB::ModbusRequest::fromRaw(rawed); 44 | std::cout << "Stringed Request 1 after rawed: " << request1.toString() << std::endl; 45 | 46 | // Add CRC to the end of raw request so that it can be loaded with CRC check 47 | rawed.insert(rawed.end(), CRCptr, CRCptr + 2); 48 | auto request2 = MB::ModbusRequest::fromRawCRC(rawed); // Throws on invalid CRC 49 | std::cout << "Stringed Request 2 after rawed: " << request2.toString() << std::endl; 50 | } 51 | 52 | int main() { createRequest(); } 53 | -------------------------------------------------------------------------------- /include/MB/Serial/connection.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "MB/modbusException.hpp" 20 | #include "MB/modbusRequest.hpp" 21 | #include "MB/modbusResponse.hpp" 22 | #include "MB/modbusUtils.hpp" 23 | 24 | namespace MB::Serial { 25 | class Connection { 26 | public: 27 | // Pretty high timeout 28 | static const unsigned int DefaultSerialTimeout = 100; 29 | 30 | private: 31 | struct termios _termios; 32 | int _fd; 33 | 34 | int _timeout = Connection::DefaultSerialTimeout; 35 | 36 | public: 37 | constexpr explicit Connection() : _termios(), _fd(-1) {} 38 | explicit Connection(const std::string &path); 39 | explicit Connection(const Connection &) = delete; 40 | explicit Connection(Connection &&) noexcept; 41 | Connection &operator=(Connection &&); 42 | ~Connection(); 43 | 44 | void connect(); 45 | 46 | std::vector sendRequest(const MB::ModbusRequest &request); 47 | std::vector sendResponse(const MB::ModbusResponse &response); 48 | std::vector sendException(const MB::ModbusException &exception); 49 | 50 | /** 51 | * @brief Sends data through the serial 52 | * @param data - Vectorized data 53 | */ 54 | std::vector send(std::vector data); 55 | 56 | void clearInput(); 57 | 58 | [[nodiscard]] std::tuple> awaitResponse(); 59 | [[nodiscard]] std::tuple> awaitRequest(); 60 | 61 | [[nodiscard]] std::vector awaitRawMessage(); 62 | 63 | void enableParity(const bool parity) { 64 | if (parity) 65 | getTTY().c_cflag |= PARENB; 66 | else 67 | getTTY().c_cflag &= ~PARENB; 68 | } 69 | 70 | void setEvenParity() { 71 | enableParity(true); 72 | getTTY().c_cflag &= ~PARODD; 73 | } 74 | 75 | void setOddParity() { 76 | enableParity(true); 77 | getTTY().c_cflag |= PARODD; 78 | } 79 | 80 | void setTwoStopBits(const bool two) { 81 | if (two) { 82 | getTTY().c_cflag |= CSTOPB; 83 | } else { 84 | getTTY().c_cflag &= ~CSTOPB; 85 | } 86 | } 87 | 88 | #define setBaud(s) \ 89 | case s: \ 90 | speed = B##s; \ 91 | break; 92 | void setBaudRate(speed_t speed) { 93 | switch (speed) { 94 | setBaud(0); 95 | setBaud(50); 96 | setBaud(75); 97 | setBaud(110); 98 | setBaud(134); 99 | setBaud(150); 100 | setBaud(200); 101 | setBaud(300); 102 | setBaud(600); 103 | setBaud(1200); 104 | setBaud(1800); 105 | setBaud(2400); 106 | setBaud(4800); 107 | setBaud(9600); 108 | setBaud(19200); 109 | setBaud(38400); 110 | setBaud(57600); 111 | setBaud(115200); 112 | setBaud(230400); 113 | default: 114 | throw std::runtime_error("Invalid baud rate"); 115 | } 116 | cfsetospeed(&_termios, speed); 117 | cfsetispeed(&_termios, speed); 118 | } 119 | #undef setBaud 120 | 121 | termios &getTTY() { return _termios; } 122 | 123 | int getTimeout() const { return _timeout; } 124 | 125 | void setTimeout(int timeout) { _timeout = timeout; } 126 | }; 127 | } // namespace MB::Serial 128 | -------------------------------------------------------------------------------- /include/MB/TCP/connection.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "MB/modbusException.hpp" 17 | #include "MB/modbusRequest.hpp" 18 | #include "MB/modbusResponse.hpp" 19 | 20 | namespace MB::TCP { 21 | class Connection { 22 | public: 23 | static const unsigned int DefaultTCPTimeout = 500; 24 | 25 | private: 26 | int _sockfd = -1; 27 | uint16_t _messageID = 0; 28 | int _timeout = Connection::DefaultTCPTimeout; 29 | 30 | public: 31 | explicit Connection() noexcept : _sockfd(-1), _messageID(0) {}; 32 | explicit Connection(int sockfd) noexcept; 33 | Connection(const Connection ©) = delete; 34 | Connection(Connection &&moved) noexcept; 35 | Connection &operator=(Connection &&other) noexcept { 36 | if (this == &other) 37 | return *this; 38 | 39 | if (_sockfd != -1 && _sockfd != other._sockfd) 40 | ::close(_sockfd); 41 | 42 | _sockfd = other._sockfd; 43 | _messageID = other._messageID; 44 | other._sockfd = -1; 45 | 46 | return *this; 47 | } 48 | 49 | [[nodiscard]] int getSockfd() const { return _sockfd; } 50 | 51 | static Connection with(std::string addr, int port); 52 | 53 | ~Connection(); 54 | 55 | std::vector sendRequest(const MB::ModbusRequest &req); 56 | std::vector sendResponse(const MB::ModbusResponse &res); 57 | std::vector sendException(const MB::ModbusException &ex); 58 | 59 | [[nodiscard]] MB::ModbusRequest awaitRequest(); 60 | [[nodiscard]] MB::ModbusResponse awaitResponse(); 61 | 62 | [[nodiscard]] std::vector awaitRawMessage(); 63 | 64 | [[nodiscard]] uint16_t getMessageId() const { return _messageID; } 65 | 66 | void setMessageId(uint16_t messageId) { _messageID = messageId; } 67 | }; 68 | } // namespace MB::TCP 69 | -------------------------------------------------------------------------------- /include/MB/TCP/server.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "connection.hpp" 16 | 17 | namespace MB::TCP { 18 | class Server { 19 | private: 20 | int _serverfd; 21 | int _port; 22 | sockaddr_in _server; 23 | 24 | public: 25 | explicit Server(int port); 26 | ~Server(); 27 | 28 | Server(const Server &) = delete; 29 | Server(Server &&moved) { 30 | _serverfd = moved._serverfd; 31 | _port = moved._port; 32 | moved._serverfd = -1; 33 | } 34 | Server &operator=(Server &&moved) { 35 | if (this == &moved) 36 | return *this; 37 | 38 | _serverfd = moved._serverfd; 39 | _port = moved._port; 40 | moved._serverfd = -1; 41 | return *this; 42 | } 43 | 44 | [[nodiscard]] int nativeHandle() { return _serverfd; } 45 | 46 | std::optional awaitConnection(); 47 | }; 48 | } // namespace MB::TCP 49 | -------------------------------------------------------------------------------- /include/MB/crc.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //! This namespace contains functions used for CRC calculation 6 | namespace MB::CRC { 7 | //! Calculates CRC based on the input buffer - C style 8 | uint16_t calculateCRC(const uint8_t *buff, std::size_t len); 9 | 10 | //! Calculate CRC based on the input vector of bytes 11 | inline uint16_t calculateCRC(const std::vector &buffer, 12 | std::optional len = std::nullopt) { 13 | std::size_t bufferLength = buffer.size(); 14 | if (len.has_value() && bufferLength >= *len) { 15 | bufferLength = *len; 16 | } 17 | 18 | return calculateCRC(static_cast(&(*buffer.begin())), bufferLength); 19 | } 20 | }; // namespace MB::CRC 21 | -------------------------------------------------------------------------------- /include/MB/modbusCell.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | /** 12 | * Namespace that contains whole project 13 | */ 14 | namespace MB { 15 | /** 16 | * @brief Class that represents single modbus cell, it is either coil(bool) or 17 | * reg(uint16_t). 18 | */ 19 | class ModbusCell { 20 | private: 21 | std::variant _value; 22 | 23 | public: 24 | /** 25 | * @brief Constructs cell with register type equal to 0. 26 | */ 27 | constexpr ModbusCell() = default; 28 | 29 | /** 30 | * @brief Constructs cell with register value. 31 | * @param reg - Register value. 32 | */ 33 | constexpr ModbusCell(uint16_t reg) : _value(reg) {}; 34 | 35 | /** 36 | * @brief Constructs cell with coil value. 37 | * @param coil - Coil value. 38 | */ 39 | constexpr ModbusCell(bool coil) : _value(coil) {}; 40 | 41 | ModbusCell(const ModbusCell &other) noexcept = default; 42 | ModbusCell &operator=(const ModbusCell &other) noexcept = default; 43 | ModbusCell &operator=(ModbusCell &&other) noexcept = default; 44 | 45 | /** 46 | * @brief Static wrapper for cell construction. 47 | * @param reg - Requested value. 48 | * @return New cell. 49 | */ 50 | [[nodiscard]] static ModbusCell initReg(uint16_t reg) { return ModbusCell(reg); } 51 | 52 | /** 53 | * @brief Static wrapper for cell construction. 54 | * @param coil - Requested value. 55 | * @return New cell. 56 | */ 57 | [[nodiscard]] static ModbusCell initCoil(bool coil) { return ModbusCell(coil); } 58 | 59 | /** 60 | * @brief Checks if cell is coil. 61 | * @returns Boolean representing result. 62 | */ 63 | [[nodiscard]] bool isCoil() const { return std::holds_alternative(_value); }; 64 | 65 | /** 66 | * @brief Checks if cell is register. 67 | * @returns Boolean representing result. 68 | */ 69 | [[nodiscard]] bool isReg() const { return std::holds_alternative(_value); }; 70 | 71 | /** 72 | * @brief Returns coil value, changes cell type if necessary. 73 | * @return Reference to coil value. 74 | */ 75 | bool &coil() { 76 | if (isReg()) 77 | _value = static_cast(std::get(_value)); 78 | return std::get(_value); 79 | }; 80 | 81 | /** 82 | * @brief Returns register value, changes cell type if necessary. 83 | * @return Reference to coil value. 84 | */ 85 | uint16_t ®() { 86 | if (isCoil()) 87 | _value = static_cast(std::get(_value)); 88 | return std::get(_value); 89 | }; 90 | 91 | /** 92 | * @brief Returns coil value. 93 | * @return Reference to coil value. 94 | * @throws bad_variant_access - When cell is of different type as requested. 95 | */ 96 | [[nodiscard]] const bool &coil() const { return std::get(_value); }; 97 | 98 | /** 99 | * @brief Returns register value. 100 | * @return Reference to coil value. 101 | * @throws bad_variant_access - When cell is of different type as requested. 102 | */ 103 | [[nodiscard]] const uint16_t ®() const { return std::get(_value); }; 104 | 105 | /** 106 | * Creates string representation of the cell. 107 | * @return String representation. 108 | */ 109 | [[nodiscard]] std::string toString() const noexcept { 110 | return isCoil() ? ((coil()) ? "true" : "false") : std::to_string(reg()); 111 | } 112 | }; 113 | } // namespace MB 114 | -------------------------------------------------------------------------------- /include/MB/modbusException.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2024 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "modbusUtils.hpp" 14 | 15 | /** 16 | * Namespace that contains whole project 17 | */ 18 | namespace MB { 19 | /** 20 | * Thic class represent Modbus exception and is 21 | * derived form std::exception. It is just a wrapper 22 | * around standard error codes and some custom codes. 23 | */ 24 | class ModbusException : public std::exception { 25 | private: 26 | uint8_t _slaveId; 27 | bool _validSlave; 28 | utils::MBErrorCode _errorCode; 29 | utils::MBFunctionCode _functionCode; 30 | 31 | public: 32 | // We do not allow default CTORs: https://github.com/Mazurel/Modbus/issues/6 33 | ModbusException() = delete; 34 | 35 | /** 36 | * @brief Constructs Exception from raw data 37 | * @param inputData is vector of bytes that will be be interpreted 38 | * @param CRC based on this param method performs CRC calculation and throws 39 | * exception if it is invalid 40 | * @note if CRC = true input data needs to contain 2 CRC bytes on back (used 41 | * in RS) 42 | * */ 43 | explicit ModbusException(const std::vector &inputData, 44 | bool CRC = false) noexcept; 45 | 46 | //! Constructs Exception based on error code, function code and slaveId 47 | explicit ModbusException( 48 | utils::MBErrorCode errorCode, uint8_t slaveId = 0xFF, 49 | utils::MBFunctionCode functionCode = utils::Undefined) noexcept 50 | : _slaveId(slaveId), _validSlave(true), _errorCode(errorCode), 51 | _functionCode(functionCode) {} 52 | 53 | /* 54 | * Check if there is Modbus error in raw modbus input 55 | * NOTE: this method doesn't detect invalid byte order, byte order is 56 | * checked at ModbusRequest/ModbusResponse 57 | * */ 58 | static bool exist(const std::vector &inputData) noexcept { 59 | if (inputData.size() < 2) // TODO Figure out better solution to such mistake 60 | return false; 61 | 62 | return inputData[1] & 0b10000000; 63 | } 64 | 65 | /* 66 | * Returns attached SlaveID 67 | * NOTE: it is worth to check if slaveId is specified with isSlaveValid() 68 | * */ 69 | [[nodiscard]] uint8_t slaveID() const noexcept { return _slaveId; } 70 | 71 | //! Checks if SlaveID is specified 72 | [[nodiscard]] bool isSlaveValid() const noexcept { return _validSlave; } 73 | 74 | //! Sets SlaveID 75 | void setSlaveID(uint8_t slaveId) noexcept { 76 | _validSlave = true; 77 | _slaveId = slaveId; 78 | } 79 | 80 | //! Returns detected error code 81 | [[nodiscard]] utils::MBErrorCode getErrorCode() const noexcept { return _errorCode; } 82 | 83 | /** 84 | * This function is less optimal, it is just to be compatible with 85 | * `std::exception`, you should preferably use toString() 86 | */ 87 | [[nodiscard]] const char *what() const noexcept override { 88 | const std::size_t MAX_STRING_SIZE = 1024; 89 | static char str[MAX_STRING_SIZE]; 90 | auto originalStr = toString(); 91 | std::strncpy(str, originalStr.c_str(), 92 | std::min(originalStr.size(), MAX_STRING_SIZE)); 93 | return str; 94 | } 95 | 96 | //! Returns string representation of object 97 | [[nodiscard]] std::string toString() const noexcept; 98 | /** 99 | * @brief Convert Modbus request object into the vector of bytes, 100 | * representing modbus frame, ready to be sent over HW interface 101 | * 102 | * @throws ModbusException - if modbus data in the object is invalid 103 | */ 104 | [[nodiscard]] std::vector toRaw() const noexcept; 105 | 106 | [[nodiscard]] utils::MBFunctionCode functionCode() const noexcept { 107 | return _functionCode; 108 | } 109 | 110 | void setFunctionCode(utils::MBFunctionCode functionCode) noexcept { 111 | _functionCode = functionCode; 112 | } 113 | }; 114 | } // namespace MB 115 | -------------------------------------------------------------------------------- /include/MB/modbusRequest.hpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2024 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "modbusCell.hpp" 12 | #include "modbusUtils.hpp" 13 | 14 | /** 15 | * Namespace that contains whole project 16 | */ 17 | namespace MB { 18 | /** 19 | * This class represent Modbus response, it allows 20 | * user to manipulate and display it in various ways. 21 | */ 22 | class ModbusRequest { 23 | private: 24 | uint8_t _slaveID; 25 | utils::MBFunctionCode _functionCode; 26 | 27 | uint16_t _address; 28 | uint16_t _registersNumber; 29 | 30 | std::vector _values; 31 | 32 | public: 33 | // We do not allow default CTORs: https://github.com/Mazurel/Modbus/issues/6 34 | ModbusRequest() = delete; 35 | 36 | /** 37 | * @brief 38 | * Constructs Request from raw data 39 | * @note 40 | * 1) if CRC = true input data needs to contain 2 CRC bytes on back (used in 41 | *RS) 42 | * @note 43 | * 2) This is private constructor, you need to use fromRaw or fromRawCRC 44 | * @param inputData - Is vector of bytes that will be be interpreted, 45 | *whereas based on CRC parameter method performs CRC calculation and throws 46 | *exception if it is invalid 47 | * @throws ModbusException 48 | **/ 49 | explicit ModbusRequest(const std::vector &inputData, 50 | bool CRC = false) noexcept(false); 51 | 52 | /* 53 | * @description Constructs Request from raw data 54 | * @params inputData is a vector of bytes that will be interpreted 55 | * @throws ModbusException 56 | **/ 57 | static ModbusRequest fromRaw(const std::vector &inputData) noexcept(false) { 58 | return ModbusRequest(inputData); 59 | } 60 | 61 | /* 62 | * @description Constructs Request from raw data and checks it's CRC 63 | * @params inputData is a vector of bytes that will be interpreted 64 | * @throws ModbusException 65 | * @note This methods performs CRC check that may throw ModbusException on 66 | * invalid CRC 67 | **/ 68 | static ModbusRequest fromRawCRC(const std::vector &inputData) { 69 | return ModbusRequest(inputData, true); 70 | } 71 | 72 | /** 73 | * Simple constructor, that allows to create "dummy" ModbusRequest 74 | * object. May be useful in some cases. 75 | */ 76 | explicit ModbusRequest( 77 | uint8_t slaveId = 0, 78 | utils::MBFunctionCode functionCode = static_cast(0), 79 | uint16_t address = 0, uint16_t registersNumber = 0, 80 | std::vector values = {}) noexcept; 81 | 82 | /** 83 | * Copy constructor for the response. 84 | */ 85 | ModbusRequest(const ModbusRequest &); 86 | 87 | /** 88 | * Equal operator for the response. 89 | */ 90 | ModbusRequest &operator=(const ModbusRequest &); 91 | 92 | //! Returns string representation of object 93 | [[nodiscard]] std::string toString() const noexcept; 94 | //! Returns raw bytes representation of object, ready for modbus 95 | //! communication 96 | [[nodiscard]] std::vector toRaw() const; 97 | 98 | //! Returns function type based on Modbus function code 99 | [[nodiscard]] utils::MBFunctionType functionType() const noexcept { 100 | return utils::functionType(_functionCode); 101 | } 102 | //! Returns register type based on Modbus function code 103 | [[nodiscard]] utils::MBFunctionRegisters functionRegisters() const noexcept { 104 | return utils::functionRegister(_functionCode); 105 | } 106 | 107 | [[nodiscard]] uint8_t slaveID() const { return _slaveID; } 108 | [[nodiscard]] utils::MBFunctionCode functionCode() const { return _functionCode; } 109 | [[nodiscard]] uint16_t registerAddress() const { return _address; } 110 | [[nodiscard]] uint16_t numberOfRegisters() const { return _registersNumber; } 111 | [[nodiscard]] const std::vector ®isterValues() const { 112 | return _values; 113 | } 114 | 115 | void setSlaveId(uint8_t slaveId) { _slaveID = slaveId; } 116 | void setFunctionCode(utils::MBFunctionCode functionCode) { 117 | _functionCode = functionCode; 118 | } 119 | void setAddress(uint16_t address) { _address = address; } 120 | void setRegistersNumber(uint16_t registersNumber) { 121 | _registersNumber = registersNumber; 122 | _values.resize(registersNumber); 123 | } 124 | void setValues(const std::vector &values) { _values = values; } 125 | }; 126 | } // namespace MB 127 | -------------------------------------------------------------------------------- /reformat-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ALL_FORMATABLE_FILES=$(find src include tests example -name '*.cpp' -o -name '*.hpp') 4 | CLANG_FORMAT_ARGS="-style=file" 5 | 6 | echo "*** Modbus Clang Format Wrapper **" 7 | clang-format --version 8 | 9 | if [[ "$DRY" = "TRUE" ]]; then 10 | diff_count=`clang-format --dry-run $CLANG_FORMAT_ARGS $ALL_FORMATABLE_FILES 2>&1 | wc -l` 11 | exit $(($diff_count > 0)) 12 | else 13 | clang-format -i --verbose $CLANG_FORMAT_ARGS $ALL_FORMATABLE_FILES 14 | fi 15 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | pkgs.mkShell rec { 3 | name = "modbus-env"; 4 | 5 | buildInputs = with pkgs; [ 6 | gcc 7 | cmake 8 | cmakeCurses 9 | doxygen 10 | libnet 11 | ]; 12 | } 13 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(MODBUS_HEADER_FILES_DIR ${PROJECT_SOURCE_DIR}/include/MB) 2 | 3 | # Include modbus core files 4 | set(CORE_HEADER_FILES ${MODBUS_HEADER_FILES_DIR}/modbusCell.hpp 5 | ${MODBUS_HEADER_FILES_DIR}/modbusException.hpp 6 | ${MODBUS_HEADER_FILES_DIR}/modbusRequest.hpp 7 | ${MODBUS_HEADER_FILES_DIR}/modbusResponse.hpp 8 | ${MODBUS_HEADER_FILES_DIR}/modbusUtils.hpp 9 | ${MODBUS_HEADER_FILES_DIR}/crc.hpp 10 | ) 11 | 12 | set(CORE_SOURCE_FILES 13 | modbusException.cpp 14 | modbusRequest.cpp 15 | modbusResponse.cpp 16 | crc.cpp 17 | ) 18 | 19 | add_library(Modbus_Core) 20 | target_sources(Modbus_Core PRIVATE ${CORE_SOURCE_FILES} INTERFACE ${CORE_HEADER_FILES}) 21 | target_include_directories(Modbus_Core PUBLIC ${PROJECT_SOURCE_DIR}/include PRIVATE ${MODBUS_HEADER_FILES_DIR}) 22 | 23 | add_library(Modbus) 24 | target_link_libraries(Modbus Modbus_Core) 25 | 26 | if(MODBUS_SERIAL_COMMUNICATION) 27 | message(STATUS "Enabling Modbus Serial") 28 | add_subdirectory(Serial) 29 | target_link_libraries(Modbus Modbus_Serial) 30 | endif() 31 | 32 | if(MODBUS_TCP_COMMUNICATION) 33 | message(STATUS "Enabling Modbus Serial") 34 | add_subdirectory(TCP) 35 | target_link_libraries(Modbus Modbus_TCP) 36 | endif() 37 | -------------------------------------------------------------------------------- /src/Serial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(MODBUS_SERIAL_HEADER_FILES ${MODBUS_HEADER_FILES_DIR}/Serial/connection.hpp) 2 | set(MODBUS_SERIAL_SOURCE_FILES connection.cpp) 3 | 4 | add_library(Modbus_Serial) 5 | target_include_directories(Modbus_Serial PUBLIC ${MODBUS_HEADER_FILES_DIR}) 6 | target_link_libraries(Modbus_Serial Modbus_Core) 7 | target_sources(Modbus_Serial PRIVATE ${MODBUS_SERIAL_SOURCE_FILES} PUBLIC ${MODBUS_SERIAL_HEADER_FILES}) 8 | -------------------------------------------------------------------------------- /src/Serial/connection.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "Serial/connection.hpp" 6 | #include "modbusUtils.hpp" 7 | #include 8 | 9 | using namespace MB::Serial; 10 | 11 | Connection::Connection(const std::string &path) { 12 | _fd = open(path.c_str(), O_RDWR | O_SYNC); 13 | 14 | if (_fd < 0) { 15 | throw std::runtime_error("Cannot open serial port " + path); 16 | } 17 | 18 | if (tcgetattr(_fd, &_termios) != 0) { 19 | throw std::runtime_error("Error at tcgetattr - " + std::to_string(errno)); 20 | } 21 | 22 | cfmakeraw(&_termios); 23 | 24 | _termios.c_iflag &= ~(PARMRK | INPCK); 25 | _termios.c_iflag |= IGNPAR; 26 | } 27 | 28 | void Connection::connect() { 29 | tcflush(_fd, TCIFLUSH); 30 | if (tcsetattr(_fd, TCSAFLUSH, &_termios) != 0) { 31 | throw std::runtime_error("Error {" + std::to_string(_fd) + "} at tcsetattr - " + 32 | std::to_string(errno)); 33 | } 34 | } 35 | 36 | Connection::~Connection() { 37 | if (_fd >= 0) 38 | ::close(_fd); 39 | _fd = -1; 40 | } 41 | 42 | std::vector Connection::sendRequest(const MB::ModbusRequest &request) { 43 | return send(request.toRaw()); 44 | } 45 | 46 | std::vector Connection::sendResponse(const MB::ModbusResponse &response) { 47 | return send(response.toRaw()); 48 | } 49 | 50 | std::vector Connection::sendException(const MB::ModbusException &exception) { 51 | return send(exception.toRaw()); 52 | } 53 | 54 | std::vector Connection::awaitRawMessage() { 55 | std::vector data(1024); 56 | 57 | pollfd waitingFD; 58 | waitingFD.fd = this->_fd; 59 | waitingFD.events = POLLIN; 60 | waitingFD.revents = POLLIN; 61 | 62 | if (::poll(&waitingFD, 1, _timeout) <= 0) { 63 | throw MB::ModbusException(MB::utils::Timeout); 64 | } 65 | 66 | auto size = ::read(_fd, data.begin().base(), 1024); 67 | 68 | if (size < 0) { 69 | throw MB::ModbusException(MB::utils::SlaveDeviceFailure); 70 | } 71 | 72 | data.resize(size); 73 | data.shrink_to_fit(); 74 | 75 | return data; 76 | } 77 | 78 | // TODO: Figure out how to return raw data when exception is being thrown 79 | std::tuple> Connection::awaitResponse() { 80 | std::vector data; 81 | data.reserve(8); 82 | 83 | MB::ModbusResponse response(0, MB::utils::ReadAnalogInputRegisters); 84 | 85 | while (true) { 86 | try { 87 | auto tmpResponse = awaitRawMessage(); 88 | data.insert(data.end(), tmpResponse.begin(), tmpResponse.end()); 89 | 90 | if (MB::ModbusException::exist(data)) 91 | throw MB::ModbusException(data); 92 | 93 | response = MB::ModbusResponse::fromRawCRC(data); 94 | break; 95 | } catch (const MB::ModbusException &ex) { 96 | if (MB::utils::isStandardErrorCode(ex.getErrorCode()) || 97 | ex.getErrorCode() == MB::utils::Timeout || 98 | ex.getErrorCode() == MB::utils::SlaveDeviceFailure) 99 | throw ex; 100 | continue; 101 | } 102 | } 103 | 104 | return std::tie(response, data); 105 | } 106 | 107 | std::tuple> Connection::awaitRequest() { 108 | std::vector data; 109 | data.reserve(8); 110 | 111 | MB::ModbusRequest request(0, MB::utils::ReadAnalogInputRegisters); 112 | 113 | while (true) { 114 | try { 115 | auto tmpResponse = awaitRawMessage(); 116 | data.insert(data.end(), tmpResponse.begin(), tmpResponse.end()); 117 | 118 | request = MB::ModbusRequest::fromRawCRC(data); 119 | break; 120 | } catch (const MB::ModbusException &ex) { 121 | if (ex.getErrorCode() == MB::utils::Timeout || 122 | ex.getErrorCode() == MB::utils::SlaveDeviceFailure) 123 | throw ex; 124 | continue; 125 | } 126 | } 127 | 128 | return std::tie(request, data); 129 | } 130 | 131 | std::vector Connection::send(std::vector data) { 132 | data.reserve(data.size() + 2); 133 | const auto crc = utils::calculateCRC(data.begin().base(), data.size()); 134 | 135 | data.push_back(reinterpret_cast(&crc)[0]); 136 | data.push_back(reinterpret_cast(&crc)[1]); 137 | 138 | // Ensure that nothing will intervene in our communication 139 | // WARNING: It may conflict with something (although it may also help in 140 | // most cases) 141 | tcflush(_fd, TCOFLUSH); 142 | // Write 143 | utils::ignore_result(write(_fd, data.begin().base(), data.size())); 144 | // It may be a good idea to use tcdrain, although it has tendency to not 145 | // work as expected tcdrain(_fd); 146 | 147 | return data; 148 | } 149 | 150 | Connection::Connection(Connection &&moved) noexcept { 151 | _fd = moved._fd; 152 | _termios = moved._termios; 153 | moved._fd = -1; 154 | } 155 | 156 | Connection &Connection::operator=(Connection &&moved) { 157 | if (this == &moved) 158 | return *this; 159 | 160 | _fd = moved._fd; 161 | memcpy(&_termios, &(moved._termios), sizeof(moved._termios)); 162 | moved._fd = -1; 163 | return *this; 164 | } 165 | -------------------------------------------------------------------------------- /src/TCP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(MODBUS_TCP_HEADER_FILES ${MODBUS_HEADER_FILES_DIR}/TCP/connection.hpp 2 | ${MODBUS_HEADER_FILES_DIR}/TCP/server.hpp) 3 | 4 | set(MODBUS_TCP_SOURCE_FILES connection.cpp server.cpp) 5 | 6 | add_library(Modbus_TCP) 7 | target_include_directories(Modbus_TCP PUBLIC ${MODBUS_HEADER_FILES_DIR}) 8 | target_link_libraries(Modbus_TCP Modbus_Core) 9 | target_sources(Modbus_TCP PRIVATE ${MODBUS_TCP_SOURCE_FILES} PUBLIC ${MODBUS_TCP_HEADER_FILES}) 10 | -------------------------------------------------------------------------------- /src/TCP/server.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "TCP/server.hpp" 6 | 7 | using namespace MB::TCP; 8 | 9 | Server::Server(int port) { 10 | _port = port; 11 | _serverfd = socket(AF_INET, SOCK_STREAM, 0); 12 | 13 | if (_serverfd == -1) 14 | throw std::runtime_error("Cannot create socket"); 15 | 16 | setsockopt(_serverfd, SOL_SOCKET, SO_REUSEADDR, new int(1), sizeof(int)); 17 | setsockopt(_serverfd, SOL_SOCKET, SO_REUSEPORT, new int(1), sizeof(int)); 18 | 19 | _server = {}; 20 | 21 | _server.sin_family = AF_INET; 22 | _server.sin_addr.s_addr = INADDR_ANY; 23 | _server.sin_port = ::htons(_port); 24 | 25 | if (::bind(_serverfd, reinterpret_cast(&_server), 26 | sizeof(_server)) < 0) 27 | throw std::runtime_error("Cannot bind socket"); 28 | 29 | ::listen(_serverfd, 255); 30 | } 31 | 32 | Server::~Server() { 33 | if (_serverfd >= 0) 34 | ::close(_serverfd); 35 | 36 | _serverfd = -1; 37 | } 38 | 39 | std::optional Server::awaitConnection() { 40 | socklen_t addrLen = sizeof(_server); 41 | 42 | auto connfd = 43 | ::accept(_serverfd, reinterpret_cast(&_server), &addrLen); 44 | 45 | if (connfd < 0) 46 | throw; 47 | 48 | return Connection(connfd); 49 | } 50 | -------------------------------------------------------------------------------- /src/crc.cpp: -------------------------------------------------------------------------------- 1 | #include "MB/crc.hpp" 2 | 3 | uint16_t MB::CRC::calculateCRC(const uint8_t *buff, std::size_t len) { 4 | constexpr uint16_t wCRCTable[] = { 5 | 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0XC601, 0X06C0, 6 | 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440, 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 7 | 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 8 | 0X0880, 0XC841, 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40, 9 | 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X1400, 0XD4C1, 10 | 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641, 0XD201, 0X12C0, 0X1380, 0XD341, 11 | 0X1100, 0XD1C1, 0XD081, 0X1040, 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 12 | 0XF281, 0X3240, 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441, 13 | 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0XFA01, 0X3AC0, 14 | 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0X2800, 0XE8C1, 0XE981, 0X2940, 15 | 0XEB01, 0X2BC0, 0X2A80, 0XEA41, 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 16 | 0XEC81, 0X2C40, 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640, 17 | 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0XA001, 0X60C0, 18 | 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X6600, 0XA6C1, 0XA781, 0X6740, 19 | 0XA501, 0X65C0, 0X6480, 0XA441, 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 20 | 0X6E80, 0XAE41, 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840, 21 | 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, 0XBE01, 0X7EC0, 22 | 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, 0XB401, 0X74C0, 0X7580, 0XB541, 23 | 0X7700, 0XB7C1, 0XB681, 0X7640, 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 24 | 0X7080, 0XB041, 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, 25 | 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440, 0X9C01, 0X5CC0, 26 | 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 27 | 0X9901, 0X59C0, 0X5880, 0X9841, 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 28 | 0X8A81, 0X4A40, 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, 29 | 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641, 0X8201, 0X42C0, 30 | 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040}; 31 | 32 | uint8_t nTemp; 33 | uint16_t wCRCWord = 0xFFFF; 34 | 35 | while (len--) { 36 | nTemp = *buff++ ^ wCRCWord; 37 | wCRCWord >>= 8; 38 | wCRCWord ^= wCRCTable[nTemp]; 39 | } 40 | return wCRCWord; 41 | } 42 | -------------------------------------------------------------------------------- /src/modbusException.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "modbusException.hpp" 6 | #include "modbusUtils.hpp" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace MB; 13 | 14 | // Construct Modbus exception from raw data 15 | ModbusException::ModbusException(const std::vector &inputData, 16 | bool checkCRC) noexcept { 17 | const std::size_t PACKET_SIZE_WITHOUT_CRC = 3; 18 | const std::size_t PACKET_SIZE_WITH_CRC = 5; 19 | 20 | if (inputData.size() != 21 | ((checkCRC) ? PACKET_SIZE_WITH_CRC : PACKET_SIZE_WITHOUT_CRC)) { 22 | _slaveId = 0xFF; 23 | _functionCode = utils::Undefined; 24 | _validSlave = false; 25 | _errorCode = utils::InvalidByteOrder; 26 | return; 27 | } 28 | 29 | _slaveId = inputData[0]; 30 | _functionCode = static_cast(0b01111111 & inputData[1]); 31 | _validSlave = true; 32 | _errorCode = static_cast(inputData[2]); 33 | 34 | if (checkCRC) { 35 | const auto actualCrc = *reinterpret_cast(&inputData[3]); 36 | const uint16_t calculatedCRC = 37 | MB::CRC::calculateCRC(inputData, PACKET_SIZE_WITHOUT_CRC); 38 | 39 | if (actualCrc != calculatedCRC) { 40 | _errorCode = utils::ErrorCodeCRCError; 41 | } 42 | } 43 | } 44 | 45 | // Returns string representation of exception 46 | std::string ModbusException::toString() const noexcept { 47 | std::string res; 48 | res += "Error on slave "; 49 | if (_validSlave) 50 | res += std::to_string(_slaveId); 51 | else 52 | res += "Unknown"; 53 | res += " - "; 54 | res += utils::mbErrorCodeToStr(_errorCode); 55 | if (_functionCode != MB::utils::Undefined) { 56 | res += " ( on function: "; 57 | res += utils::mbFunctionToStr(_functionCode); 58 | res += " )"; 59 | } 60 | return res; 61 | } 62 | 63 | std::vector ModbusException::toRaw() const noexcept { 64 | std::vector result(3); 65 | 66 | result[0] = _slaveId; 67 | result[1] = static_cast(_errorCode | 0b10000000); 68 | result[2] = static_cast(_functionCode); 69 | 70 | return result; 71 | } 72 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(Google_tests) 2 | add_subdirectory(googletest) 3 | include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) 4 | 5 | if (MSVC) 6 | set(gtest_force_shared_crt on) 7 | add_compile_options(/MT) 8 | endif() 9 | 10 | set(TestFiles MB/ModbusRequestTests.cpp 11 | MB/ModbusResponseTests.cpp 12 | MB/ModbusExceptionTests.cpp 13 | MB/ModbusCellTests.cpp 14 | MB/ModbusFunctionalTests.cpp 15 | main.cpp) 16 | 17 | add_executable(Google_Tests_run ${TestFiles}) 18 | 19 | target_link_libraries(Google_Tests_run Modbus_Core) 20 | target_link_libraries(Google_Tests_run gtest gtest_main) 21 | -------------------------------------------------------------------------------- /tests/MB/ModbusCellTests.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "MB/modbusCell.hpp" 6 | #include "MB/modbusException.hpp" 7 | #include "MB/modbusUtils.hpp" 8 | #include "gtest/gtest.h" 9 | 10 | TEST(ModbusCell, Manipulation) { 11 | auto cell1 = MB::ModbusCell::initReg(12); 12 | EXPECT_EQ(cell1.reg(), 12); 13 | EXPECT_TRUE(cell1.coil()); 14 | cell1.coil() = false; 15 | EXPECT_FALSE(cell1.coil()); 16 | EXPECT_EQ(cell1.reg(), 0); 17 | cell1.reg() = 3; 18 | EXPECT_EQ(cell1.reg(), 3); 19 | } 20 | -------------------------------------------------------------------------------- /tests/MB/ModbusExceptionTests.cpp: -------------------------------------------------------------------------------- 1 | // Modbus for c++ 2 | // Copyright (c) 2020 Mateusz Mazur aka Mazurel 3 | // Licensed under: MIT License 4 | 5 | #include "MB/modbusException.hpp" 6 | #include "gtest/gtest.h" 7 | 8 | TEST(ModbusException, Exists) { 9 | EXPECT_TRUE(MB::ModbusException::exist({0x0A, 0x81, 0x02})); 10 | EXPECT_TRUE(MB::ModbusException::exist( 11 | {0x01, MB::utils::WriteMultipleDiscreteOutputCoils | 0b10000000, 0x02})); 12 | } 13 | 14 | TEST(ModbusException, Other) { 15 | EXPECT_EQ(MB::ModbusException({0x0A, 0x82, 0x02}).functionCode(), 16 | MB::utils::ReadDiscreteInputContacts); 17 | } 18 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mateusz on 19.03.2020. 3 | // 4 | 5 | #include "gtest/gtest.h" 6 | 7 | int main(int argc, char **argv) { 8 | ::testing::InitGoogleTest(&argc, argv); 9 | return RUN_ALL_TESTS(); 10 | } --------------------------------------------------------------------------------