#pragma once #include #include #include #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_CFG_TOKEN_MAX_LEN 64 #define FRAME_AP_PASSWORD_LEN 10 #define FRAME_DEVICE_ID_LEN 12 /* 6-byte STA MAC as lowercase hex */ 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]; /* Per-frame token issued by the server via GET /frame/config after * this device first introduces itself by id (see frame_client.c's * build_url). Not set at the captive portal; empty until the server * pushes one. */ char device_token[FRAME_CFG_TOKEN_MAX_LEN + 1]; } frame_config_t; /** * This device's stable identity as reported to the server (?id= on every * request): the full 6-byte STA MAC as 12 lowercase hex chars. Derived * from the same MAC the provisioning AP SSID suffix comes from; never * stored. out must hold at least FRAME_DEVICE_ID_LEN + 1 bytes. */ void frame_device_id_get(char *out, size_t out_size); /** * Persists (only) the server-issued per-frame device token -- called * from the wake cycle when GET /frame/config delivers one. Deliberately * touches nothing else: unlike frame_config_save() it must not reset * the connected-once flag or invalidate the WiFi fast-connect cache, * since nothing about the network changed. */ void frame_config_set_device_token(const char *token); /** * 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); /** * Erases the stored home-network config (SSID/password/tools server) so the * device falls back into provisioning on its next boot. Leaves the softAP * identity (SSID/password) untouched, since that's tied to the device * itself, not a particular home network -- regenerating it on every reset * would force re-scanning the join QR code for no reason. Also leaves the * last-displayed-photo CRC (below) untouched -- it describes what's * physically on screen, not network config, and stays valid regardless. */ void frame_config_clear(void); /** * Returns the CRC32 of the last frame actually written to the panel via a * physical refresh. Returns ESP_ERR_NVS_NOT_FOUND if nothing's been * displayed yet. */ esp_err_t frame_config_get_last_display_crc32(uint32_t *out); /** Records the CRC32 of the frame just displayed, for next time. */ void frame_config_set_last_display_crc32(uint32_t crc32); /** * Invalidates the tracked last-displayed-photo CRC. Call this whenever * something other than a tracked photo fetch writes to the panel (status * screens, QR onboarding) -- otherwise a later photo fetch that happens * to produce the same CRC as whatever photo was showing *before* the * panel got overwritten would wrongly skip refreshing back onto it, * leaving the other screen stuck on-screen indefinitely. */ void frame_config_invalidate_last_display_crc32(void); /** * Returns the hold_duration_ms the server most recently reported via GET * /frame/config (see frame_client.c's fetch_frame_config/frame_client_run) * -- how long NEXT/BACK must be held before next_button_check()/ * back_button_check() treat it as a hold-for-global-action instead of a * short press. Returns ESP_ERR_NVS_NOT_FOUND if the device has never * fetched one yet (fresh install/factory reset); caller should fall back * to CONFIG_FRAME_HOLD_ACTION_MS in that case. * * Deliberately a *previous* cycle's value: this cycle's own button * decision happens in main.c before WiFi even connects, but * /frame/config isn't fetched until near the end of frame_client_run * (after the image fetch, for connection-warmth/timeout reasons -- see * its own comment) -- so there's no same-cycle fresh value to use yet. */ esp_err_t frame_config_get_hold_duration_ms(uint32_t *out); /** Persists the hold duration reported by the server, for the *next* * boot's button-hold decision to use. */ void frame_config_set_hold_duration_ms(uint32_t ms); /** * 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); /** * Cached parameters from the most recent successful home-WiFi connection, * letting the next wake's first connect attempt skip the all-channel scan * (known BSSID/channel) and DHCP (known static IP/netmask/gateway/DNS). * Fields are stored exactly as esp-wifi/esp-netif already use them * internally, so they can be fed straight back in with no conversion. */ typedef struct { uint8_t bssid[6]; uint8_t channel; uint32_t ip; uint32_t netmask; uint32_t gateway; uint32_t dns; /* 0 = none cached (best-effort; a real DHCP fallback still repopulates this) */ } frame_wifi_cache_t; /** * Loads the cached fast-connect parameters. Returns false if there's * nothing cached yet, or it was invalidated (see frame_wifi_cache_clear). */ bool frame_wifi_cache_load(frame_wifi_cache_t *out); /** Saves fast-connect parameters after a successful home-WiFi connection. */ void frame_wifi_cache_save(const frame_wifi_cache_t *cache); /** * Clears the fast-connect cache. Called after a cached fast-connect * attempt itself fails (BSSID/channel went stale), after a full fetch * cycle fails despite a successful connection (the cached static IP may * be unreachable even though the link came up), and by * frame_config_save()/frame_config_clear() -- a (re)provisioning event * means whatever was cached may belong to a different network entirely. */ void frame_wifi_cache_clear(void);