Compare commits
3 Commits
16e0709a53
...
1b5b3cd8ca
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b5b3cd8ca | |||
| 802035d38b | |||
| 8b679be22a |
@ -50,11 +50,6 @@ On **first boot**, the device creates a captive Wi-Fi access point:
|
|||||||
|
|
||||||
That IP becomes your **pump control dashboard**
|
That IP becomes your **pump control dashboard**
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
>
|
|
||||||
> If you enter wrong credentials, the device will **not** connect.
|
|
||||||
> You’ll need to [**factory reset**](#factory_reset) and try again.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -652,7 +652,7 @@
|
|||||||
const payload = { ssid: ssid, password: password };
|
const payload = { ssid: ssid, password: password };
|
||||||
try {
|
try {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
const timeoutId = setTimeout(() => controller.abort(), 15000);
|
||||||
const response = await fetch('/settings', {
|
const response = await fetch('/settings', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@ -660,6 +660,8 @@
|
|||||||
signal: controller.signal
|
signal: controller.signal
|
||||||
});
|
});
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
showToast(`Wi-Fi credentials sent to device`, false);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
let errorText = `Error ${response.status}`;
|
let errorText = `Error ${response.status}`;
|
||||||
try {
|
try {
|
||||||
@ -669,12 +671,16 @@
|
|||||||
throw new Error(errorText);
|
throw new Error(errorText);
|
||||||
}
|
}
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
console.log('Wi-Fi settings saved:', result);
|
|
||||||
showToast(`✓ Wi-Fi credentials sent to device`, false);
|
if (!result.success) {
|
||||||
|
throw new Error(result.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
showToast(result.message, false);
|
||||||
passwordInput.value = "";
|
passwordInput.value = "";
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let errMsg = "✗ Connection failed";
|
let errMsg = "✗ Connection failed";
|
||||||
if (error.name === 'AbortError') errMsg = "✗ Request timeout (5s)";
|
if (error.name === 'AbortError') errMsg = "✗ Request timeout (15s)";
|
||||||
else if (error.message) errMsg = `✗ ${error.message}`;
|
else if (error.message) errMsg = `✗ ${error.message}`;
|
||||||
showToast(errMsg, true);
|
showToast(errMsg, true);
|
||||||
}
|
}
|
||||||
|
|||||||
132
main/main.c
132
main/main.c
@ -137,7 +137,7 @@ static const error_info_t error_table[] = {
|
|||||||
{APP_ERR_ADC_CALIB_FAIL, "ADC calibration failed", false},
|
{APP_ERR_ADC_CALIB_FAIL, "ADC calibration failed", false},
|
||||||
{APP_ERR_PUMP_INIT_FAIL, "Pump GPIO initialization failed", true},
|
{APP_ERR_PUMP_INIT_FAIL, "Pump GPIO initialization failed", true},
|
||||||
{APP_ERR_WIFI_INIT_FAIL, "WiFi initialization failed", true},
|
{APP_ERR_WIFI_INIT_FAIL, "WiFi initialization failed", true},
|
||||||
{APP_ERR_WIFI_CONNECT_FAIL, "WiFi connection failed", false},
|
{APP_ERR_WIFI_CONNECT_FAIL, "WiFi connection failed", true},
|
||||||
{APP_ERR_MDNS_INIT_FAIL, "mDNS service initialization failed", false},
|
{APP_ERR_MDNS_INIT_FAIL, "mDNS service initialization failed", false},
|
||||||
{APP_ERR_HTTP_SERVER_START_FAIL, "HTTP server start failed", false},
|
{APP_ERR_HTTP_SERVER_START_FAIL, "HTTP server start failed", false},
|
||||||
{APP_ERR_TASK_CREATE_FAIL, "Task creation failed", true},
|
{APP_ERR_TASK_CREATE_FAIL, "Task creation failed", true},
|
||||||
@ -479,6 +479,10 @@ static app_error_t pump_init(void) {
|
|||||||
// WiFi functions
|
// WiFi functions
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
// Добавьте в глобальные переменные:
|
||||||
|
static bool g_wifi_test_in_progress = false;
|
||||||
|
|
||||||
|
// Дополните существующий wifi_event_handler:
|
||||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||||
int32_t event_id, void* event_data) {
|
int32_t event_id, void* event_data) {
|
||||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||||
@ -486,14 +490,16 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
|||||||
ESP_LOGI(TAG, "Attempting to connect to WiFi...");
|
ESP_LOGI(TAG, "Attempting to connect to WiFi...");
|
||||||
}
|
}
|
||||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
if (retry_count < MAX_RETRY_COUNT) {
|
if (g_wifi_test_in_progress) {
|
||||||
|
// Если идет тестирование, сразу сигнализируем об ошибке
|
||||||
|
xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
|
||||||
|
} else if (retry_count < MAX_RETRY_COUNT) {
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
retry_count++;
|
retry_count++;
|
||||||
ESP_LOGI(TAG, "Retry connecting (%d/%d)...", retry_count, MAX_RETRY_COUNT);
|
ESP_LOGI(TAG, "Retry connecting (%d/%d)...", retry_count, MAX_RETRY_COUNT);
|
||||||
} else {
|
} else {
|
||||||
xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
|
xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
|
||||||
ESP_LOGE(TAG, "Failed to connect after %d retries", MAX_RETRY_COUNT);
|
ESP_LOGE(TAG, "Failed to connect after %d retries", MAX_RETRY_COUNT);
|
||||||
handle_error(APP_ERR_WIFI_CONNECT_FAIL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
@ -504,6 +510,75 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_wifi_credentials(const char* ssid, const char* password, int timeout_ms) {
|
||||||
|
wifi_config_t old_config;
|
||||||
|
esp_wifi_get_config(WIFI_IF_STA, &old_config);
|
||||||
|
|
||||||
|
if (wifi_event_group == NULL) {
|
||||||
|
wifi_event_group = xEventGroupCreate();
|
||||||
|
if (wifi_event_group == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Failed to create event group");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очищаем предыдущие биты
|
||||||
|
xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT);
|
||||||
|
|
||||||
|
// Устанавливаем флаг тестирования
|
||||||
|
g_wifi_test_in_progress = true;
|
||||||
|
|
||||||
|
// Останавливаем текущее подключение если есть
|
||||||
|
esp_wifi_disconnect();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
|
||||||
|
// Настраиваем STA интерфейс с новыми credentials
|
||||||
|
wifi_config_t wifi_config = {0};
|
||||||
|
strncpy((char*)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid) - 1);
|
||||||
|
strncpy((char*)wifi_config.sta.password, password, sizeof(wifi_config.sta.password) - 1);
|
||||||
|
wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
||||||
|
|
||||||
|
esp_err_t ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to set WiFi config: %s", esp_err_to_name(ret));
|
||||||
|
g_wifi_test_in_progress = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запускаем подключение
|
||||||
|
ret = esp_wifi_connect();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to start WiFi connection: %s", esp_err_to_name(ret));
|
||||||
|
g_wifi_test_in_progress = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Testing WiFi connection to SSID: %s", ssid);
|
||||||
|
|
||||||
|
// Ожидаем результат
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(wifi_event_group,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
|
pdFALSE,
|
||||||
|
pdFALSE,
|
||||||
|
timeout_ms / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
bool success = (bits & WIFI_CONNECTED_BIT) != 0;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ESP_LOGI(TAG, "✓ Successfully connected to %s", ssid);
|
||||||
|
esp_wifi_disconnect();
|
||||||
|
|
||||||
|
esp_wifi_set_config(WIFI_IF_STA, &old_config);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "✗ Failed to connect to %s", ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_wifi_test_in_progress = false;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
static app_error_t wifi_softap_init(void) {
|
static app_error_t wifi_softap_init(void) {
|
||||||
CHECK_ERROR(esp_netif_init(), APP_ERR_WIFI_INIT_FAIL);
|
CHECK_ERROR(esp_netif_init(), APP_ERR_WIFI_INIT_FAIL);
|
||||||
CHECK_ERROR(esp_event_loop_create_default(), APP_ERR_WIFI_INIT_FAIL);
|
CHECK_ERROR(esp_event_loop_create_default(), APP_ERR_WIFI_INIT_FAIL);
|
||||||
@ -517,6 +592,9 @@ static app_error_t wifi_softap_init(void) {
|
|||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
CHECK_ERROR(esp_wifi_init(&cfg), APP_ERR_WIFI_INIT_FAIL);
|
CHECK_ERROR(esp_wifi_init(&cfg), APP_ERR_WIFI_INIT_FAIL);
|
||||||
|
|
||||||
|
esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL);
|
||||||
|
esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL);
|
||||||
|
|
||||||
wifi_config_t wifi_config = {
|
wifi_config_t wifi_config = {
|
||||||
.ap = {
|
.ap = {
|
||||||
.ssid = CONFIG_AP_WIFI_SSID,
|
.ssid = CONFIG_AP_WIFI_SSID,
|
||||||
@ -826,27 +904,69 @@ static esp_err_t parse_wifi_settings_json(const char *content, char *ssid, char
|
|||||||
|
|
||||||
static esp_err_t setup_set_settings_handler(httpd_req_t *req) {
|
static esp_err_t setup_set_settings_handler(httpd_req_t *req) {
|
||||||
char *content = NULL;
|
char *content = NULL;
|
||||||
|
|
||||||
if (receive_http_content(req, &content) != ESP_OK) {
|
if (receive_http_content(req, &content) != ESP_OK) {
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "{\"success\":false,\"message\":\"Failed to receive content\"}");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char ssid[WIFI_SSID_MAX_LEN];
|
char ssid[WIFI_SSID_MAX_LEN];
|
||||||
char password[WIFI_PASS_MAX_LEN];
|
char password[WIFI_PASS_MAX_LEN];
|
||||||
|
|
||||||
if (parse_wifi_settings_json(content, ssid, password) != ESP_OK) {
|
if (parse_wifi_settings_json(content, ssid, password) != ESP_OK) {
|
||||||
free(content);
|
free(content);
|
||||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Missing or invalid 'ssid' or 'password' parameters");
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "{\"success\":false,\"message\":\"Missing or invalid 'ssid' or 'password' parameters\"}");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
free(content);
|
free(content);
|
||||||
|
|
||||||
send_json_response(req, "{\"success\":true}");
|
// Проверяем, что пароль не пустой для защищенных сетей
|
||||||
|
if (strlen(ssid) == 0) {
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "{\"success\":false,\"message\":\"SSID cannot be empty\"}");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Testing WiFi connection to SSID: %s", ssid);
|
||||||
|
|
||||||
|
// Сохраняем текущий режим WiFi перед тестированием
|
||||||
|
wifi_mode_t current_mode;
|
||||||
|
esp_wifi_get_mode(¤t_mode);
|
||||||
|
|
||||||
|
// Убеждаемся, что STA режим активен
|
||||||
|
if (!(current_mode & WIFI_MODE_STA)) {
|
||||||
|
esp_wifi_set_mode(WIFI_MODE_APSTA);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_ok = test_wifi_credentials(ssid, password, 15000); // 15 секунд таймаут
|
||||||
|
|
||||||
|
if (wifi_ok) {
|
||||||
save_wifi_config(ssid, password);
|
save_wifi_config(ssid, password);
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_set_status(req, HTTPD_200);
|
||||||
|
const char *success_response = "{\"success\":true,\"message\":\"WiFi connected successfully! Rebooting in 2 seconds...\"}";
|
||||||
|
httpd_resp_send(req, success_response, strlen(success_response));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "WiFi test SUCCESSFUL, rebooting...");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
esp_restart();
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
const char *error_response = "{\"success\":false,\"message\":\"Failed to connect to WiFi. Please check SSID and password.\"}";
|
||||||
|
httpd_resp_send(req, error_response, strlen(error_response));
|
||||||
|
|
||||||
|
ESP_LOGW(TAG, "WiFi test FAILED for SSID: %s", ssid);
|
||||||
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static esp_err_t setup_get_wifi_list_handler(httpd_req_t *req) {
|
static esp_err_t setup_get_wifi_list_handler(httpd_req_t *req) {
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
uint16_t ap_count = 0;
|
uint16_t ap_count = 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user