DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ble_gatt.h
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 ble_gatt.h
6 * @brief Bluetooth ATT protocol codec + GATT characteristic bridge (DETWS_ENABLE_BLE_GATT).
7 *
8 * The ESP32's BLE radio is on-chip, but bridging GATT to the web still needs the wire protocol under
9 * GATT - the **Attribute Protocol** (ATT, Bluetooth Core Vol 3 Part F): the read / write / notify /
10 * error PDUs a central and peripheral exchange, each a 1-byte opcode followed by a little-endian
11 * attribute handle and value. This is that codec (build + parse the common ATT PDUs) plus a small
12 * characteristic table serializer that exposes discovered / offered GATT characteristics as JSON for the
13 * web stack.
14 *
15 * Pure, zero heap, no stdlib, host-testable. The BLE stack (NimBLE / Bluedroid) owns the radio; this owns
16 * the ATT bytes and the northbound JSON.
17 */
18
19#ifndef DETERMINISTICESPASYNCWEBSERVER_BLE_GATT_H
20#define DETERMINISTICESPASYNCWEBSERVER_BLE_GATT_H
21
22#include "ServerConfig.h"
23#include <stddef.h>
24#include <stdint.h>
25
26#if DETWS_ENABLE_BLE_GATT
27
28/** @brief ATT opcodes (subset). */
29struct AttOp
30{
31 static constexpr uint8_t ATT_OP_ERROR_RSP = 0x01; ///< [op][req-op][handle:2][error]
32 static constexpr uint8_t ATT_OP_READ_REQ = 0x0A; ///< [op][handle:2]
33 static constexpr uint8_t ATT_OP_READ_RSP = 0x0B; ///< [op][value...]
34 static constexpr uint8_t ATT_OP_WRITE_REQ = 0x12; ///< [op][handle:2][value...]
35 static constexpr uint8_t ATT_OP_WRITE_RSP = 0x13; ///< [op]
36 static constexpr uint8_t ATT_OP_HANDLE_VALUE_NTF = 0x1B; ///< [op][handle:2][value...]
37};
38
39/** @brief GATT characteristic property bits (declaration properties byte). */
40struct GattProp
41{
42 static constexpr uint8_t GATT_PROP_READ = 0x02;
43 static constexpr uint8_t GATT_PROP_WRITE_NR = 0x04; ///< write without response.
44 static constexpr uint8_t GATT_PROP_WRITE = 0x08;
45 static constexpr uint8_t GATT_PROP_NOTIFY = 0x10;
46 static constexpr uint8_t GATT_PROP_INDICATE = 0x20;
47};
48
49/** @brief Build a Read Request: [0x0A][handle:2 LE]. @return 3, or 0 on overflow. */
50size_t att_read_req(uint16_t handle, uint8_t *out, size_t cap);
51
52/** @brief Build a Read Response: [0x0B][value...]. @return 1+vlen, or 0 on overflow. */
53size_t att_read_rsp(const uint8_t *val, size_t vlen, uint8_t *out, size_t cap);
54
55/** @brief Build a Write Request: [0x12][handle:2 LE][value...]. @return 3+vlen, or 0 on overflow. */
56size_t att_write_req(uint16_t handle, const uint8_t *val, size_t vlen, uint8_t *out, size_t cap);
57
58/** @brief Build a Handle Value Notification: [0x1B][handle:2 LE][value...]. @return 3+vlen, or 0. */
59size_t att_notify(uint16_t handle, const uint8_t *val, size_t vlen, uint8_t *out, size_t cap);
60
61/** @brief Build an Error Response: [0x01][req-op][handle:2 LE][error]. @return 5, or 0 on overflow. */
62size_t att_error_rsp(uint8_t req_op, uint16_t handle, uint8_t error, uint8_t *out, size_t cap);
63
64/** @brief A parsed ATT PDU (value points into the input). */
65struct AttPdu
66{
67 uint8_t opcode;
68 uint16_t handle; ///< set for opcodes that carry a handle (else 0).
69 uint8_t req_op; ///< for ERROR_RSP: the failed request opcode.
70 uint8_t error; ///< for ERROR_RSP: the error code.
71 const uint8_t *value; ///< value payload (null if none).
72 size_t value_len;
73};
74
75/** @brief Parse an ATT PDU into @p out. @return true if @p len >= 1 and the fixed fields fit. */
76bool att_parse(const uint8_t *pdu, size_t len, AttPdu *out);
77
78/** @brief One GATT characteristic for the northbound bridge. */
79struct GattChar
80{
81 uint16_t handle;
82 uint16_t uuid; ///< 16-bit UUID (assigned-number form).
83 uint8_t props; ///< GATT_PROP_* bits.
84};
85
86/**
87 * @brief Serialize a characteristic table as `[{"handle":H,"uuid":"0xXXXX","props":P},...]` for the web.
88 * @return length written (excl NUL), or 0 on overflow / bad args.
89 */
90size_t gatt_char_json(const GattChar *chars, size_t n, char *out, size_t cap);
91
92#endif // DETWS_ENABLE_BLE_GATT
93#endif // DETERMINISTICESPASYNCWEBSERVER_BLE_GATT_H
User-facing configuration for DeterministicESPAsyncWebServer.