DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
modbus_master.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file modbus_master.cpp
6 * @brief Modbus TCP master codec - build read requests, parse responses (pure).
7 */
8
10
11#if DETWS_ENABLE_MODBUS_MASTER
12
13size_t modbus_build_read(uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out,
14 size_t cap)
15{
16 if (!out || cap < 12)
17 return 0;
18 if (fc != 0x03 && fc != 0x04) // read holding / input registers only
19 return 0;
20 if (count < 1 || count > 125)
21 return 0;
22
23 // MBAP header
24 out[0] = (uint8_t)(txid >> 8);
25 out[1] = (uint8_t)(txid & 0xFF);
26 out[2] = 0; // protocol id (Modbus) = 0
27 out[3] = 0;
28 out[4] = 0; // length = unit(1) + PDU(5) = 6
29 out[5] = 6;
30 out[6] = unit;
31 // PDU
32 out[7] = fc;
33 out[8] = (uint8_t)(start >> 8);
34 out[9] = (uint8_t)(start & 0xFF);
35 out[10] = (uint8_t)(count >> 8);
36 out[11] = (uint8_t)(count & 0xFF);
37 return 12;
38}
39
40int modbus_parse_response(const uint8_t *adu, size_t len, uint16_t *regs_out, size_t max_regs, uint8_t *exception_out)
41{
42 if (exception_out)
43 *exception_out = 0;
44 if (!adu || len < 9) // MBAP(7) + FC(1) + at least one more byte
45 return -1;
46 if (adu[2] != 0 || adu[3] != 0) // protocol id must be 0
47 return -1;
48
49 uint8_t fc = adu[7];
50 if (fc & 0x80) // exception response: FC | 0x80, then the exception code
51 {
52 if (exception_out)
53 *exception_out = adu[8];
54 return 0;
55 }
56 if (fc != 0x03 && fc != 0x04)
57 return -1;
58
59 uint8_t byte_count = adu[8];
60 if ((byte_count & 1) || len < (size_t)(9 + byte_count)) // must be even and present
61 return -1;
62
63 int nregs = byte_count / 2;
64 int copied = 0;
65 for (int i = 0; i < nregs && (size_t)i < max_regs; i++)
66 {
67 if (regs_out)
68 regs_out[i] = (uint16_t)((adu[9 + i * 2] << 8) | adu[9 + i * 2 + 1]);
69 copied++;
70 }
71 return copied;
72}
73
74#endif // DETWS_ENABLE_MODBUS_MASTER
Modbus TCP master codec + register scanner (DETWS_ENABLE_MODBUS_MASTER).