/* SPDX-License-Identifier: GPL-3.0-only */ /* Native ESP-IDF Wi-Fi lifecycle and connection policy manager. */ #pragma once #include #include #include "esp_err.h" #include "esp_wifi_types.h" #include "wifi_config.h" #ifdef __cplusplus extern "C" { #endif typedef enum { WIFI_MANAGER_STATE_STOPPED = 0, WIFI_MANAGER_STATE_STARTING, WIFI_MANAGER_STATE_CONNECTING, WIFI_MANAGER_STATE_WAITING_IP, WIFI_MANAGER_STATE_ONLINE, WIFI_MANAGER_STATE_BACKOFF, WIFI_MANAGER_STATE_AP_ONLY, WIFI_MANAGER_STATE_ERROR, } wifi_manager_state_t; typedef struct { uint64_t starts; uint64_t stops; uint64_t applies; uint64_t connect_attempts; uint64_t associations; uint64_t got_ip; uint64_t disconnects; uint64_t profile_cycles; uint64_t retries; uint64_t ap_starts; uint64_t ap_stops; uint64_t client_joins; uint64_t client_leaves; uint64_t queue_drops; } wifi_manager_counters_t; typedef struct { bool initialized; bool started; wifi_manager_state_t state; /* -1 means that no station profile is currently being attempted or used. */ int8_t active_profile; uint8_t sta_ssid_len; char sta_ssid[WIFI_CONFIG_SSID_MAX_LEN + 1U]; uint32_t ip; uint32_t netmask; uint32_t gateway; uint8_t sta_channel; int8_t sta_rssi; wifi_auth_mode_t sta_auth; wifi_config_ap_policy_t ap_policy; bool ap_running; uint8_t ap_ssid_len; char ap_ssid[WIFI_CONFIG_SSID_MAX_LEN + 1U]; uint8_t ap_client_count; uint8_t ap_channel; uint16_t last_disconnect_reason; esp_err_t last_error; uint32_t retry_seconds; uint32_t config_generation; wifi_manager_counters_t counters; } wifi_manager_snapshot_t; /* * Initializes ESP-NETIF, the default event loop, both default Wi-Fi netifs, * Wi-Fi itself, and the permanent policy task. The manager never aborts the * application on failure; callers may keep UART/USB services operational. */ esp_err_t wifi_manager_init(const wifi_app_config_t *config); /* Returns a copy of the RAM working configuration, including credentials. */ esp_err_t wifi_manager_get_working_config(wifi_app_config_t *config); /* * Replaces the RAM working configuration. Disabled-profile-only edits do not * interrupt a running radio; changes to effective station/AP policy are * applied asynchronously by restarting with the newest generation. */ esp_err_t wifi_manager_apply_working_config(const wifi_app_config_t *config); /* Secret-free working projection, copied together with runtime under the mutex. * Zero wait: ESP_ERR_TIMEOUT means no snapshot was obtained. Password presence * is the only credential metadata, needed to stage/enable disabled profiles. */ typedef struct { uint8_t enabled, priority; wifi_config_security_t security; uint8_t ssid_len, ssid[WIFI_CONFIG_SSID_MAX_LEN]; bool password_configured; } wifi_manager_profile_settings_t; typedef struct { wifi_manager_snapshot_t runtime; uint8_t enabled_at_boot, ap_channel; wifi_config_ap_policy_t ap_policy; uint8_t ap_ssid_len, ap_ssid[WIFI_CONFIG_SSID_MAX_LEN]; bool ap_password_configured; wifi_manager_profile_settings_t profiles[WIFI_CONFIG_STA_PROFILE_COUNT]; } wifi_manager_settings_t; esp_err_t wifi_manager_get_settings(wifi_manager_settings_t *settings); enum { WIFI_PATCH_BOOT = 1U << 0, WIFI_PATCH_POLICY = 1U << 1, WIFI_PATCH_CHANNEL = 1U << 2, WIFI_PATCH_ENABLED = 1U << 3, WIFI_PATCH_PRIORITY = 1U << 4, WIFI_PATCH_SECURITY = 1U << 5, WIFI_PATCH_SSID = 1U << 6, WIFI_PATCH_PASSWORD = 1U << 7, }; /* profile=-1 selects AP/global fields; 0..3 selects a station profile. * Absent bits preserve CURRENT bytes, never a stale caller's secret copy. * PASSWORD with length zero clears only when canonical validation permits it. * Caller owns and must wipe this transient input after every exit path. */ typedef struct { uint32_t fields; int8_t profile; uint8_t enabled_at_boot, ap_channel, enabled, priority; wifi_config_ap_policy_t ap_policy; wifi_config_security_t security; uint8_t ssid_len, ssid[WIFI_CONFIG_SSID_MAX_LEN]; uint8_t password_len, password[WIFI_CONFIG_PSK_MAX_LEN]; } wifi_manager_patch_t; /* Dispatcher-only conditional operations. A nonzero expected generation must * match under the mutation mutex; ESP_ERR_NOT_FOUND denotes stale selection. * No generation wrap/reuse. Queue failure leaves RAM untouched. */ esp_err_t wifi_manager_patch_current(uint32_t generation, const wifi_manager_patch_t *patch); esp_err_t wifi_manager_save_current(uint32_t generation); /* Stored-only load: never generates or installs unknown default credentials. */ esp_err_t wifi_manager_load_current(uint32_t generation); /* Lifecycle requests are asynchronous and serialized by the manager task. */ esp_err_t wifi_manager_start(void); esp_err_t wifi_manager_stop(void); esp_err_t wifi_manager_reconnect(void); /* Advance to the next enabled station profile in priority order, wrapping safely. */ esp_err_t wifi_manager_next_profile(void); /* Reannounce the configured hostname when the manager currently has a STA IP. */ esp_err_t wifi_manager_mdns_reannounce(void); /* Snapshot data never contains station or AP passwords. */ esp_err_t wifi_manager_get_snapshot(wifi_manager_snapshot_t *snapshot); esp_err_t wifi_manager_clear_counters(void); const char *wifi_manager_state_to_string(wifi_manager_state_t state); #ifdef __cplusplus } #endif