Files
espresso_frame/firmware/main/wifi_provisioning.h
T
tfaour d32236d832 Add two ways back into provisioning: RST press and repeated server failure
RST/power-on trigger: checks esp_reset_reason() at the very top of boot.
ESP32-C6 can't electrically distinguish the RST/EN button from a genuine
power-on (both report ESP_RST_POWERON -- confirmed against ESP-IDF's own
docs, ESP_RST_EXT is explicitly "not applicable"), so POWERON is treated
as "user wants to reconfigure" and routes straight to provisioning. Safe
because the device's only normal restart path is ESP_RST_DEEPSLEEP (its
own scheduled wake), and crash-type resets (brownout/watchdog/panic)
report their own distinct reasons, not POWERON -- so a flaky power supply
or transient crash won't get bounced into provisioning, only an actual
power cycle or RST press will (which plausibly means the frame is being
moved/redeployed anyway).

Auto-fallback: a new NVS-persisted consecutive-failure counter
(frame_config_record_server_failure/reset_server_failures) tracks wakes
where the tools server was unreachable. After
CONFIG_FRAME_REPROVISION_AFTER_FAILURES in a row (default 12, ~1hr at the
retry interval), the device clears its stored WiFi config and
esp_restart()s rather than calling wifi_provisioning_start() directly --
doing that inline would mean initializing the display driver a second
time in the same session (frame_client_run already did once), the same
class of double-init bug hit earlier with WiFi. The next boot's
frame_config_load() naturally reports "not provisioned" and routes
through the existing, already-tested provisioning path with a single
fresh epd_init(). Solves the "I moved the server to a new address" case
without needing USB access.

Both frame_config_save() (fresh provisioning) and any successful server
contact reset the failure counter.
2026-07-18 16:10:03 -04:00

75 lines
2.7 KiB
C

#pragma once
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#define FRAME_CFG_SSID_MAX_LEN 32
#define FRAME_CFG_PASSWORD_MAX_LEN 64
#define FRAME_CFG_SERVER_MAX_LEN 128
#define FRAME_AP_PASSWORD_LEN 10
typedef struct {
char sta_ssid[FRAME_CFG_SSID_MAX_LEN + 1];
char sta_password[FRAME_CFG_PASSWORD_MAX_LEN + 1];
char toolsserver[FRAME_CFG_SERVER_MAX_LEN + 1];
} frame_config_t;
/**
* Loads the saved home-network config from NVS.
* Returns ESP_ERR_NVS_NOT_FOUND if the device has never been provisioned.
*/
esp_err_t frame_config_load(frame_config_t *out);
/** Saves the home-network config to NVS. Resets the "connected once"
* flag below, since this is a fresh (re)provisioning event. */
esp_err_t frame_config_save(const frame_config_t *cfg);
/**
* Whether the device has already shown the post-connect status screen at
* least once since the current WiFi config was saved. Used so the status
* screen always shows on the first connection after (re)provisioning, but
* is skipped on later successful wakes to save an extra refresh.
*/
bool frame_config_has_connected_once(void);
/** Marks the status screen as having been shown for the current WiFi config. */
void frame_config_mark_connected_once(void);
/**
* Increments the persisted count of consecutive wakes where the tools
* server was unreachable. Returns true once it reaches
* CONFIG_FRAME_REPROVISION_AFTER_FAILURES, signaling the caller should
* fall back to provisioning instead of just retrying again.
*/
bool frame_config_record_server_failure(void);
/** Resets the consecutive-server-failure count. Call on any successful
* contact with the tools server. */
void frame_config_reset_server_failures(void);
/**
* Erases the saved home-network config (SSID/password/toolsserver) so the
* next boot's frame_config_load() reports "not provisioned" and falls
* back into provisioning. Doesn't touch the AP password or other
* device-identity state. Follow with esp_restart() -- doesn't itself
* bring up provisioning, since that would mean initializing the display
* driver a second time in a session that may have already done so.
*/
esp_err_t frame_config_clear(void);
/**
* Returns this device's provisioning AP identity: a fixed SSID (from
* Kconfig) and a password that's generated once on first use and persisted
* in NVS from then on. The password is drawn from an easy-to-type charset
* since it's shown on the e-ink panel (as both a QR code and plaintext) and
* may need to be typed in by hand.
*/
void ap_identity_get(char *ssid_out, size_t ssid_len, char *pass_out, size_t pass_len);
/**
* Brings up the ESPRESSO softAP + captive portal (DNS + HTTP) so the user
* can provision the device. Does not return.
*/
void wifi_provisioning_start(void);