├── .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 | [](https://github.com/Mazurel/Modbus/actions/workflows/cmake-multi-platform.yml)
4 | [](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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
76 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
80 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
80 |
81 |
82 |
84 | connection.hpp
85 |
86 | server.hpp
87 |
88 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
80 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
80 |
81 |
82 |
84 | connection.hpp
85 |
86 |
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 |
24 | Modbus cpp
25 | 0.1
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
68 |
69 |
Here is a list of all modules:
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
76 |
77 |
Here is a list of all documented namespaces with brief descriptions:
78 |
[detail level 1 2 ]
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 |
26 | Modbus cpp 0.1
27 |
28 |
29 |
30 |
31 |
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 |
76 |
77 |
Here is a list of all related documentation pages:
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 |
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 | }
--------------------------------------------------------------------------------