Add Wi-Fi next-profile rotation control
This commit is contained in:
@@ -80,6 +80,7 @@ typedef enum {
|
||||
LOCAL_STATUS_ACTION_SERIAL = 0,
|
||||
LOCAL_STATUS_ACTION_WIFI_POWER,
|
||||
LOCAL_STATUS_ACTION_WIFI_RECONNECT,
|
||||
LOCAL_STATUS_ACTION_WIFI_NEXT_PROFILE,
|
||||
LOCAL_STATUS_ACTION_WEB,
|
||||
LOCAL_STATUS_ACTION_SSH,
|
||||
LOCAL_STATUS_ACTION_REVOKE_WRITER,
|
||||
@@ -695,6 +696,8 @@ static const char *action_label(local_status_action_t action,
|
||||
return snapshot->wifi_available && snapshot->wifi.started ? "WiFi:stop" : "WiFi:start";
|
||||
case LOCAL_STATUS_ACTION_WIFI_RECONNECT:
|
||||
return "WiFi:reconnect";
|
||||
case LOCAL_STATUS_ACTION_WIFI_NEXT_PROFILE:
|
||||
return "WiFi:next profile";
|
||||
case LOCAL_STATUS_ACTION_WEB:
|
||||
return snapshot->web_available && snapshot->web.running ? "HTTPS:stop" : "HTTPS:start";
|
||||
case LOCAL_STATUS_ACTION_SSH:
|
||||
@@ -736,6 +739,8 @@ static const char *confirmed_action_label(const local_status_ui_state_t *state)
|
||||
return state->confirmed_stop ? "WiFi:stop" : "WiFi:start";
|
||||
case LOCAL_STATUS_ACTION_WIFI_RECONNECT:
|
||||
return "WiFi:reconnect";
|
||||
case LOCAL_STATUS_ACTION_WIFI_NEXT_PROFILE:
|
||||
return "WiFi:next profile";
|
||||
case LOCAL_STATUS_ACTION_WEB:
|
||||
return state->confirmed_stop ? "HTTPS:stop" : "HTTPS:start";
|
||||
case LOCAL_STATUS_ACTION_SSH:
|
||||
@@ -760,6 +765,7 @@ static bool action_requires_confirmation(local_status_action_t action,
|
||||
case LOCAL_STATUS_ACTION_WIFI_POWER:
|
||||
return snapshot->wifi_available && snapshot->wifi.started;
|
||||
case LOCAL_STATUS_ACTION_WIFI_RECONNECT:
|
||||
case LOCAL_STATUS_ACTION_WIFI_NEXT_PROFILE:
|
||||
return true;
|
||||
case LOCAL_STATUS_ACTION_WEB:
|
||||
return snapshot->web_available && snapshot->web.running;
|
||||
@@ -1047,6 +1053,12 @@ static void execute_action(local_status_ui_state_t *state,
|
||||
: ESP_ERR_INVALID_STATE;
|
||||
requested = error == ESP_OK;
|
||||
break;
|
||||
case LOCAL_STATUS_ACTION_WIFI_NEXT_PROFILE:
|
||||
error = snapshot->wifi_available && snapshot->wifi.started
|
||||
? wifi_manager_next_profile()
|
||||
: ESP_ERR_INVALID_STATE;
|
||||
requested = error == ESP_OK;
|
||||
break;
|
||||
case LOCAL_STATUS_ACTION_WEB:
|
||||
if (!snapshot->web_available || snapshot->web.running != state->confirmed_stop) {
|
||||
error = ESP_ERR_INVALID_STATE;
|
||||
|
||||
+6
-3
@@ -27,7 +27,7 @@ static void print_usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" wifi status|profiles|counters|clear-counters\n");
|
||||
printf(" wifi start|stop|reconnect\n");
|
||||
printf(" wifi start|stop|reconnect|next-profile\n");
|
||||
printf(" wifi profile set <slot> <priority> <mixed|wpa3> <ssid>\n");
|
||||
printf(" wifi profile secret <slot>\n");
|
||||
printf(" wifi profile enable|disable|delete <slot>\n");
|
||||
@@ -580,8 +580,10 @@ static int queue_lifecycle(const char *operation)
|
||||
error = wifi_manager_start();
|
||||
} else if (strcmp(operation, "stop") == 0) {
|
||||
error = wifi_manager_stop();
|
||||
} else {
|
||||
} else if (strcmp(operation, "reconnect") == 0) {
|
||||
error = wifi_manager_reconnect();
|
||||
} else {
|
||||
error = wifi_manager_next_profile();
|
||||
}
|
||||
if (error != ESP_OK) {
|
||||
printf("Could not queue Wi-Fi %s: %s\n", operation, esp_err_to_name(error));
|
||||
@@ -617,7 +619,8 @@ static int command_wifi(int argc, char **argv)
|
||||
}
|
||||
if (argc == 2 && (strcmp(argv[1], "start") == 0 ||
|
||||
strcmp(argv[1], "stop") == 0 ||
|
||||
strcmp(argv[1], "reconnect") == 0)) {
|
||||
strcmp(argv[1], "reconnect") == 0 ||
|
||||
strcmp(argv[1], "next-profile") == 0)) {
|
||||
return queue_lifecycle(argv[1]);
|
||||
}
|
||||
if (argc == 7 && strcmp(argv[1], "profile") == 0 &&
|
||||
|
||||
@@ -34,6 +34,7 @@ typedef enum {
|
||||
MESSAGE_COMMAND_STOP,
|
||||
MESSAGE_COMMAND_APPLY,
|
||||
MESSAGE_COMMAND_RECONNECT,
|
||||
MESSAGE_COMMAND_NEXT_PROFILE,
|
||||
MESSAGE_STA_CONNECTED,
|
||||
MESSAGE_STA_DISCONNECTED,
|
||||
MESSAGE_STA_GOT_IP,
|
||||
@@ -488,6 +489,58 @@ static void start_next_profile(manager_runtime_t *runtime)
|
||||
schedule_cycle_retry(runtime);
|
||||
}
|
||||
|
||||
static void start_next_profile_after_current(manager_runtime_t *runtime)
|
||||
{
|
||||
wifi_app_config_t config;
|
||||
copy_working_config(&config);
|
||||
uint8_t order[WIFI_CONFIG_STA_PROFILE_COUNT];
|
||||
uint8_t count = build_profile_order(order, &config);
|
||||
int8_t active_profile;
|
||||
lock_shared();
|
||||
active_profile = s_shared.snapshot.active_profile;
|
||||
unlock_shared();
|
||||
|
||||
if (count == 0U) {
|
||||
wifi_config_secure_wipe(&config, sizeof(config));
|
||||
set_last_error(ESP_ERR_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t active_index = 0U;
|
||||
bool found_active = false;
|
||||
for (uint8_t index = 0U; index < count; ++index) {
|
||||
if (active_profile >= 0 && order[index] == (uint8_t)active_profile) {
|
||||
active_index = index;
|
||||
found_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (uint8_t index = 0U; index < count; ++index) {
|
||||
uint8_t source = found_active ? (uint8_t)((active_index + 1U + index) % count)
|
||||
: index;
|
||||
runtime->profile_order[index] = order[source];
|
||||
}
|
||||
runtime->profile_count = count;
|
||||
runtime->next_profile = 0U;
|
||||
runtime->attempt_deadline = 0;
|
||||
runtime->disconnect_deadline = 0;
|
||||
runtime->backoff_deadline = 0;
|
||||
runtime->stable_deadline = 0;
|
||||
runtime->advance_after_disconnect = true;
|
||||
|
||||
uint32_t intentional_disconnects = runtime->intentional_disconnects;
|
||||
mark_intentional_disconnect(runtime);
|
||||
if (runtime->intentional_disconnects == intentional_disconnects) {
|
||||
runtime->advance_after_disconnect = false;
|
||||
start_next_profile(runtime);
|
||||
} else {
|
||||
/* Recover if the bounded queue drops the matching disconnect event. */
|
||||
runtime->disconnect_deadline = esp_timer_get_time() +
|
||||
WIFI_MANAGER_DISCONNECT_SETTLE_US;
|
||||
}
|
||||
wifi_config_secure_wipe(&config, sizeof(config));
|
||||
}
|
||||
|
||||
static void start_profile_cycle(manager_runtime_t *runtime)
|
||||
{
|
||||
wifi_app_config_t config;
|
||||
@@ -767,6 +820,12 @@ static void handle_message(manager_runtime_t *runtime,
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_COMMAND_NEXT_PROFILE:
|
||||
if (manager_is_started()) {
|
||||
start_next_profile_after_current(runtime);
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_STA_CONNECTED:
|
||||
if (!manager_is_started() ||
|
||||
!connected_event_matches_active_profile(message)) {
|
||||
@@ -1356,6 +1415,11 @@ esp_err_t wifi_manager_reconnect(void)
|
||||
return enqueue_lifecycle_command(MESSAGE_COMMAND_RECONNECT, -1);
|
||||
}
|
||||
|
||||
esp_err_t wifi_manager_next_profile(void)
|
||||
{
|
||||
return enqueue_lifecycle_command(MESSAGE_COMMAND_NEXT_PROFILE, -1);
|
||||
}
|
||||
|
||||
esp_err_t wifi_manager_get_snapshot(wifi_manager_snapshot_t *snapshot)
|
||||
{
|
||||
if (snapshot == NULL) {
|
||||
|
||||
@@ -92,6 +92,8 @@ esp_err_t wifi_manager_apply_working_config(const wifi_app_config_t *config);
|
||||
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);
|
||||
|
||||
/* Snapshot data never contains station or AP passwords. */
|
||||
esp_err_t wifi_manager_get_snapshot(wifi_manager_snapshot_t *snapshot);
|
||||
|
||||
Reference in New Issue
Block a user