Files
ESP32_Serial_Swiss_Army_Knife/src/wifi_manager.h

156 lines
5.4 KiB
C

/* SPDX-License-Identifier: GPL-3.0-only */
/* Native ESP-IDF Wi-Fi lifecycle and connection policy manager. */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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