DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
provisioning_service.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 provisioning_service.h
6 * @brief First-boot WiFi provisioning via a captive portal (DETWS_ENABLE_PROVISIONING).
7 *
8 * When no WiFi credentials are stored, the device starts a softAP and a
9 * catch-all DNS responder (via the transport-layer UDP service - no add-on library) so any
10 * connected client is funneled to a credentials form. Submitted SSID/passphrase
11 * are persisted to NVS and the device reboots into station mode. Uses only
12 * `WiFi.softAP`, lwIP UDP, and `Preferences`; compiled to stubs when disabled
13 * or off-Arduino.
14 *
15 * The form-field parser (detws_prov_form_field) is always compiled and is the
16 * only non-trivial logic, so it is unit-tested off-target.
17 *
18 * @author Douglas Quigg (dstroy0)
19 * @date 2026
20 */
21
22#ifndef DETERMINISTICESPASYNCWEBSERVER_PROVISIONING_SERVICE_H
23#define DETERMINISTICESPASYNCWEBSERVER_PROVISIONING_SERVICE_H
24
25#include "ServerConfig.h"
26#include <stddef.h>
27
28class DetWebServer;
29
30/**
31 * @brief Extract and URL-decode a field from an x-www-form-urlencoded body.
32 *
33 * Finds `@p key=` in @p body (matching only whole field names, i.e. at the
34 * start or just after `&`), copies its value up to the next `&` or end into
35 * @p out, decoding `+` to space and `%XX` hex escapes. Always null-terminates.
36 *
37 * @param body Form body (e.g. "ssid=My+AP&psk=p%40ss").
38 * @param key Field name (e.g. "ssid").
39 * @param out Destination buffer.
40 * @param cap Capacity of @p out (>= 1).
41 * @return true if the field was found, false otherwise (out set to "").
42 */
43bool detws_prov_form_field(const char *body, const char *key, char *out, size_t cap);
44
45/**
46 * @brief Load stored WiFi credentials from NVS.
47 * @param ssid Destination for the stored SSID (always null-terminated).
48 * @param ssid_cap Capacity of @p ssid.
49 * @param psk Destination for the stored passphrase (always null-terminated).
50 * @param psk_cap Capacity of @p psk.
51 * @return true if a non-empty SSID is stored (the app should connect in STA mode).
52 */
53bool detws_provisioning_load(char *ssid, size_t ssid_cap, char *psk, size_t psk_cap);
54
55/**
56 * @brief Start the captive portal: softAP @p ap_ssid + catch-all DNS + form routes.
57 *
58 * Registers `GET /*` (the credentials form) and `POST /save` (persist + reboot)
59 * on @p server. The catch-all DNS responder runs from a transport-layer UDP callback,
60 * so no per-loop servicing is required. Call after server.begin().
61 */
62void detws_provisioning_begin(DetWebServer &server, const char *ap_ssid);
63
64/** @brief Erase stored credentials (forces re-provisioning on next boot). */
66
67#endif // DETERMINISTICESPASYNCWEBSERVER_PROVISIONING_SERVICE_H
User-facing configuration for DeterministicESPAsyncWebServer.
Single-port HTTP server with deterministic, zero-allocation execution.
Definition dwserver.h:348
void detws_provisioning_begin(DetWebServer &server, const char *ap_ssid)
Start the captive portal: softAP ap_ssid + catch-all DNS + form routes.
bool detws_prov_form_field(const char *body, const char *key, char *out, size_t cap)
Extract and URL-decode a field from an x-www-form-urlencoded body.
bool detws_provisioning_load(char *ssid, size_t ssid_cap, char *psk, size_t psk_cap)
Load stored WiFi credentials from NVS.
void detws_provisioning_clear()
Erase stored credentials (forces re-provisioning on next boot).