optimize AP mode
Some checks failed
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 6m44s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 3m59s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 3m51s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 3m52s
Some checks failed
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 6m44s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 3m59s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 3m51s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 3m52s
- save wifi data - show status led Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -12,4 +12,5 @@ idf_component_register(SRCS
|
||||
esp_event
|
||||
json
|
||||
simulator
|
||||
persistence-manager
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <esp_http_server.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <persistence_manager.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -116,6 +117,17 @@ esp_err_t api_wifi_scan_handler(httpd_req_t *req)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void reboot_task(void *param)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
static bool is_valid(const cJSON *string)
|
||||
{
|
||||
return string && cJSON_IsString(string) && string->valuestring && strlen(string->valuestring) > 0;
|
||||
}
|
||||
|
||||
esp_err_t api_wifi_config_handler(httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGI(TAG, "POST /api/wifi/config");
|
||||
@@ -128,12 +140,22 @@ esp_err_t api_wifi_config_handler(httpd_req_t *req)
|
||||
}
|
||||
buf[ret] = '\0';
|
||||
|
||||
// Passwort maskieren
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json)
|
||||
{
|
||||
cJSON *ssid = cJSON_GetObjectItem(json, "ssid");
|
||||
cJSON *pw = cJSON_GetObjectItem(json, "password");
|
||||
if (pw && cJSON_IsString(pw) && pw->valuestring)
|
||||
if (is_valid(ssid) && is_valid(pw))
|
||||
{
|
||||
persistence_manager_t pm;
|
||||
if (persistence_manager_init(&pm, "wifi_config") == ESP_OK)
|
||||
{
|
||||
persistence_manager_set_string(&pm, "ssid", ssid->valuestring);
|
||||
persistence_manager_set_string(&pm, "password", pw->valuestring);
|
||||
persistence_manager_deinit(&pm);
|
||||
}
|
||||
}
|
||||
if (is_valid(pw))
|
||||
{
|
||||
size_t pwlen = strlen(pw->valuestring);
|
||||
char *masked = malloc(pwlen + 1);
|
||||
@@ -163,7 +185,9 @@ esp_err_t api_wifi_config_handler(httpd_req_t *req)
|
||||
ESP_LOGI(TAG, "Received WiFi config: %s", buf);
|
||||
}
|
||||
|
||||
// TODO: Parse JSON and connect to WiFi
|
||||
// Define a reboot task function
|
||||
xTaskCreate(reboot_task, "reboot_task", 2048, NULL, 5, NULL);
|
||||
|
||||
set_cors_headers(req);
|
||||
httpd_resp_set_status(req, "200 OK");
|
||||
return httpd_resp_sendstr(req, "{\"status\":\"ok\"}");
|
||||
|
||||
@@ -18,7 +18,7 @@ static void ws_clients_init(void)
|
||||
}
|
||||
|
||||
// Add a client to the list
|
||||
static void add_client(int fd)
|
||||
static bool add_client(int fd)
|
||||
{
|
||||
for (int i = 0; i < WS_MAX_CLIENTS; i++)
|
||||
{
|
||||
@@ -27,10 +27,11 @@ static void add_client(int fd)
|
||||
ws_clients[i] = fd;
|
||||
ws_client_count++;
|
||||
ESP_LOGI(TAG, "WebSocket client connected: fd=%d (total: %d)", fd, ws_client_count);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "Max WebSocket clients reached, cannot add fd=%d", fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove a client from the list
|
||||
@@ -83,6 +84,13 @@ esp_err_t websocket_handler(httpd_req_t *req)
|
||||
{
|
||||
// This is the handshake
|
||||
ESP_LOGI(TAG, "WebSocket handshake");
|
||||
int fd = httpd_req_to_sockfd(req);
|
||||
if (!add_client(fd))
|
||||
{
|
||||
// Zu viele Clients, Verbindung schließen
|
||||
httpd_sess_trigger_close(req->handle, fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ static void dns_server_task(void *pvParameters)
|
||||
// Fragen: 1, Antworten: 1
|
||||
buf[7] = 1;
|
||||
// Antwort anhängen (Name Pointer auf Frage)
|
||||
int qlen = len - 12;
|
||||
int pos = len;
|
||||
buf[pos++] = 0xC0;
|
||||
buf[pos++] = 0x0C; // Name pointer
|
||||
|
||||
@@ -16,204 +16,120 @@
|
||||
#include <lwip/sys.h>
|
||||
#include <mdns.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <persistence_manager.h>
|
||||
#include <sdkconfig.h>
|
||||
#include <string.h>
|
||||
|
||||
// Event group to signal when we are connected
|
||||
// Event group to signal WiFi connection status
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
// The bits for the event group
|
||||
// Event group bits
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static const char *TAG = "wifi_manager";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
static int s_current_network_index = 0;
|
||||
|
||||
// WiFi network configuration structure
|
||||
typedef struct
|
||||
static void wifi_create_ap()
|
||||
{
|
||||
const char *ssid;
|
||||
const char *password;
|
||||
} wifi_network_config_t;
|
||||
|
||||
// Array of configured WiFi networks
|
||||
static const wifi_network_config_t s_wifi_networks[] = {
|
||||
#if CONFIG_WIFI_ENABLED
|
||||
{CONFIG_WIFI_SSID_1, CONFIG_WIFI_PASSWORD_1},
|
||||
#if CONFIG_WIFI_NETWORK_COUNT >= 2
|
||||
{CONFIG_WIFI_SSID_2, CONFIG_WIFI_PASSWORD_2},
|
||||
#endif
|
||||
#if CONFIG_WIFI_NETWORK_COUNT >= 3
|
||||
{CONFIG_WIFI_SSID_3, CONFIG_WIFI_PASSWORD_3},
|
||||
#endif
|
||||
#if CONFIG_WIFI_NETWORK_COUNT >= 4
|
||||
{CONFIG_WIFI_SSID_4, CONFIG_WIFI_PASSWORD_4},
|
||||
#endif
|
||||
#if CONFIG_WIFI_NETWORK_COUNT >= 5
|
||||
{CONFIG_WIFI_SSID_5, CONFIG_WIFI_PASSWORD_5},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int s_wifi_network_count = sizeof(s_wifi_networks) / sizeof(s_wifi_networks[0]);
|
||||
|
||||
static void try_next_network(void);
|
||||
|
||||
static void connect_to_network(int index)
|
||||
{
|
||||
#if CONFIG_WIFI_ENABLED
|
||||
if (index >= s_wifi_network_count)
|
||||
{
|
||||
ESP_LOGE(TAG, "No more networks to try");
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
return;
|
||||
}
|
||||
|
||||
const wifi_network_config_t *network = &s_wifi_networks[index];
|
||||
|
||||
// Skip empty SSIDs
|
||||
if (network->ssid == NULL || strlen(network->ssid) == 0)
|
||||
{
|
||||
ESP_LOGW(TAG, "Skipping empty SSID at index %d", index);
|
||||
s_current_network_index++;
|
||||
s_retry_num = 0;
|
||||
try_next_network();
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_DIAG_EVENT(TAG, "Trying to connect to network %d: %s", index + 1, network->ssid);
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta =
|
||||
{
|
||||
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||
},
|
||||
};
|
||||
|
||||
strncpy((char *)wifi_config.sta.ssid, network->ssid, sizeof(wifi_config.sta.ssid) - 1);
|
||||
strncpy((char *)wifi_config.sta.password, network->password, sizeof(wifi_config.sta.password) - 1);
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
esp_wifi_connect();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void try_next_network(void)
|
||||
{
|
||||
#if CONFIG_WIFI_ENABLED
|
||||
s_current_network_index++;
|
||||
s_retry_num = 0;
|
||||
|
||||
if (s_current_network_index < s_wifi_network_count)
|
||||
{
|
||||
connect_to_network(s_current_network_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to connect to any configured network");
|
||||
led_behavior_t led0_behavior = {
|
||||
.index = 0,
|
||||
.mode = LED_MODE_BLINK,
|
||||
.color = {.red = 50, .green = 0, .blue = 0},
|
||||
.on_time_ms = 1000,
|
||||
.off_time_ms = 500,
|
||||
};
|
||||
led_status_set_behavior(led0_behavior);
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
#if CONFIG_WIFI_ENABLED
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||
{
|
||||
led_behavior_t led0_behavior = {
|
||||
.index = 0,
|
||||
.mode = LED_MODE_BLINK,
|
||||
.color = {.red = 50, .green = 50, .blue = 0},
|
||||
.on_time_ms = 200,
|
||||
.off_time_ms = 200,
|
||||
};
|
||||
led_status_set_behavior(led0_behavior);
|
||||
|
||||
connect_to_network(s_current_network_index);
|
||||
}
|
||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||
{
|
||||
if (s_retry_num < CONFIG_WIFI_CONNECT_RETRIES)
|
||||
{
|
||||
led_behavior_t led0_behavior = {
|
||||
.index = 0,
|
||||
.mode = LED_MODE_BLINK,
|
||||
.color = {.red = 50, .green = 50, .blue = 0},
|
||||
.on_time_ms = 200,
|
||||
.off_time_ms = 200,
|
||||
};
|
||||
led_status_set_behavior(led0_behavior);
|
||||
|
||||
s_retry_num++;
|
||||
ESP_DIAG_EVENT(TAG, "Retrying network %d (%d/%d)", s_current_network_index + 1, s_retry_num,
|
||||
CONFIG_WIFI_CONNECT_RETRIES);
|
||||
esp_wifi_connect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Retries exhausted for current network, try next one
|
||||
ESP_LOGW(TAG, "Failed to connect to network %d after %d retries, trying next...", s_current_network_index + 1,
|
||||
CONFIG_WIFI_CONNECT_RETRIES);
|
||||
try_next_network();
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||
{
|
||||
led_behavior_t led0_behavior = {
|
||||
.index = 0,
|
||||
.mode = LED_MODE_SOLID,
|
||||
.color = {.red = 0, .green = 50, .blue = 0},
|
||||
};
|
||||
led_status_set_behavior(led0_behavior);
|
||||
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
ESP_DIAG_EVENT(TAG, "Got IP address:" IPSTR " (network %d: %s)", IP2STR(&event->ip_info.ip),
|
||||
s_current_network_index + 1, s_wifi_networks[s_current_network_index].ssid);
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void wifi_manager_init()
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
s_retry_num = 0;
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Access Point erstellen
|
||||
esp_netif_create_default_wifi_ap();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_stop());
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
wifi_config_t ap_config = {.ap = {.ssid = "system-control",
|
||||
.ssid_len = strlen("system-control"),
|
||||
.password = "",
|
||||
.max_connection = 4,
|
||||
.authmode = WIFI_AUTH_OPEN}};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_LOGI(TAG, "Access Point 'system-control' started");
|
||||
dns_server_start("192.168.4.1");
|
||||
|
||||
ESP_LOGI(TAG, "Access Point 'system-control' gestartet");
|
||||
led_behavior_t led_behavior = {
|
||||
.color = {.red = 50, .green = 0, .blue = 0},
|
||||
.index = 0,
|
||||
.mode = LED_MODE_SOLID,
|
||||
};
|
||||
led_status_set_behavior(led_behavior);
|
||||
}
|
||||
|
||||
// DNS Hijack Server starten (alle DNS-Anfragen auf AP-IP umleiten)
|
||||
dns_server_start("192.168.4.1"); // ggf. dynamisch ermitteln
|
||||
void wifi_manager_init()
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
// API-Server starten
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Try to load stored WiFi configuration
|
||||
persistence_manager_t pm;
|
||||
char ssid[33] = {0};
|
||||
char password[65] = {0};
|
||||
bool have_ssid = false, have_password = false;
|
||||
if (persistence_manager_init(&pm, "wifi_config") == ESP_OK)
|
||||
{
|
||||
persistence_manager_get_string(&pm, "ssid", ssid, sizeof(ssid), "");
|
||||
persistence_manager_get_string(&pm, "password", password, sizeof(password), "");
|
||||
have_ssid = strlen(ssid) > 0;
|
||||
have_password = strlen(password) > 0;
|
||||
}
|
||||
|
||||
if (have_ssid && have_password)
|
||||
{
|
||||
led_behavior_t led_behavior = {
|
||||
.on_time_ms = 250,
|
||||
.off_time_ms = 100,
|
||||
.color = {.red = 50, .green = 50, .blue = 0},
|
||||
.index = 0,
|
||||
.mode = LED_MODE_BLINK,
|
||||
};
|
||||
led_status_set_behavior(led_behavior);
|
||||
|
||||
ESP_LOGI(TAG, "Found WiFi configuration: SSID='%s'", ssid);
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
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_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
int retries = 0;
|
||||
EventBits_t bits;
|
||||
do
|
||||
{
|
||||
esp_wifi_connect();
|
||||
bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE,
|
||||
5000 / portTICK_PERIOD_MS);
|
||||
if (bits & WIFI_CONNECTED_BIT)
|
||||
{
|
||||
led_behavior_t led_behavior = {
|
||||
.index = 0,
|
||||
.color = {.red = 0, .green = 50, .blue = 0},
|
||||
.mode = LED_MODE_SOLID,
|
||||
};
|
||||
led_status_set_behavior(led_behavior);
|
||||
ESP_LOGI(TAG, "WiFi connection established successfully");
|
||||
break;
|
||||
}
|
||||
retries++;
|
||||
} while (!(bits & WIFI_CONNECTED_BIT) && retries < CONFIG_WIFI_CONNECT_RETRIES);
|
||||
|
||||
if (!(bits & WIFI_CONNECTED_BIT))
|
||||
{
|
||||
ESP_LOGW(TAG, "WiFi connection failed, switching to Access Point mode");
|
||||
wifi_create_ap();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create Access Point
|
||||
esp_netif_create_default_wifi_ap();
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
wifi_create_ap();
|
||||
}
|
||||
|
||||
// API server start
|
||||
api_server_config_t s_config = API_SERVER_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(api_server_start(&s_config));
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t h;
|
||||
uint8_t s;
|
||||
uint8_t v;
|
||||
float h;
|
||||
float s;
|
||||
float v;
|
||||
} hsv_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
@@ -45,10 +45,10 @@ rgb_t interpolate_color_hsv(rgb_t start, rgb_t end, float factor)
|
||||
|
||||
// Interpolate HSV values
|
||||
hsv_t interpolated_hsv;
|
||||
interpolated_hsv.h = fmod(h1 + (h2 - h1) * factor, 360.0);
|
||||
if (interpolated_hsv.h < 0)
|
||||
interpolated_hsv.h = fmodf(h1 + (h2 - h1) * factor, 360.0f);
|
||||
if (interpolated_hsv.h < 0.0f)
|
||||
{
|
||||
interpolated_hsv.h += 360.0;
|
||||
interpolated_hsv.h += 360.0f;
|
||||
}
|
||||
interpolated_hsv.s = start_hsv.s + (end_hsv.s - start_hsv.s) * factor;
|
||||
interpolated_hsv.v = start_hsv.v + (end_hsv.v - start_hsv.v) * factor;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <stdbool.h>
|
||||
@@ -33,14 +34,14 @@ extern "C"
|
||||
* @param pm Pointer to the persistence manager structure.
|
||||
* @param nvs_namespace Namespace to use for NVS operations.
|
||||
*/
|
||||
void persistence_manager_init(persistence_manager_t *pm, const char *nvs_namespace);
|
||||
esp_err_t persistence_manager_init(persistence_manager_t *pm, const char *nvs_namespace);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the persistence manager and release resources.
|
||||
*
|
||||
* @param pm Pointer to the persistence manager structure.
|
||||
*/
|
||||
void persistence_manager_deinit(persistence_manager_t *pm);
|
||||
esp_err_t persistence_manager_deinit(persistence_manager_t *pm);
|
||||
|
||||
/**
|
||||
* @brief Check if the persistence manager is initialized.
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#define TAG "persistence_manager"
|
||||
|
||||
void persistence_manager_init(persistence_manager_t *pm, const char *nvs_namespace)
|
||||
esp_err_t persistence_manager_init(persistence_manager_t *pm, const char *nvs_namespace)
|
||||
{
|
||||
if (!pm)
|
||||
return;
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
strncpy(pm->nvs_namespace, nvs_namespace ? nvs_namespace : "config", sizeof(pm->nvs_namespace) - 1);
|
||||
pm->nvs_namespace[sizeof(pm->nvs_namespace) - 1] = '\0';
|
||||
pm->initialized = false;
|
||||
@@ -16,20 +16,20 @@ void persistence_manager_init(persistence_manager_t *pm, const char *nvs_namespa
|
||||
{
|
||||
pm->initialized = true;
|
||||
ESP_LOGI(TAG, "Initialized with namespace: %s", pm->nvs_namespace);
|
||||
return ESP_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to open NVS handle: %s", esp_err_to_name(err));
|
||||
}
|
||||
ESP_LOGE(TAG, "Failed to open NVS handle: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
void persistence_manager_deinit(persistence_manager_t *pm)
|
||||
esp_err_t persistence_manager_deinit(persistence_manager_t *pm)
|
||||
{
|
||||
if (pm && pm->initialized)
|
||||
{
|
||||
nvs_close(pm->nvs_handle);
|
||||
pm->initialized = false;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool persistence_manager_is_initialized(const persistence_manager_t *pm)
|
||||
|
||||
@@ -186,10 +186,7 @@ void app_task(void *args)
|
||||
setup_buttons();
|
||||
init_ui();
|
||||
|
||||
#if CONFIG_WIFI_ENABLED
|
||||
wifi_manager_init();
|
||||
analytics_init();
|
||||
#endif
|
||||
|
||||
start_simulation();
|
||||
|
||||
|
||||
@@ -27,25 +27,9 @@
|
||||
</button>
|
||||
</div>
|
||||
<h1>🚂 System Control</h1>
|
||||
<p data-i18n="captive.subtitle">WLAN-Einrichtung</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div id="scan-section">
|
||||
<button class="btn btn-secondary" onclick="scanNetworks()" data-i18n="captive.scan">
|
||||
📡 Netzwerke suchen
|
||||
</button>
|
||||
|
||||
<div id="loading" class="loading">
|
||||
<div class="spinner"></div>
|
||||
<p data-i18n="captive.scanning">Suche nach Netzwerken...</p>
|
||||
</div>
|
||||
|
||||
<div id="network-list" class="network-list" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<div class="divider"><span data-i18n="captive.or.manual">oder manuell eingeben</span></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ssid" data-i18n="wifi.ssid">WLAN-Name (SSID)</label>
|
||||
<input type="text" id="ssid" data-i18n-placeholder="wifi.ssid.placeholder"
|
||||
@@ -62,7 +46,8 @@
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary" onclick="saveWifi()" data-i18n="captive.connect">
|
||||
<button class="btn btn-primary" id="connect-btn" onclick="saveWifi()" data-i18n="captive.connect"
|
||||
disabled>
|
||||
💾 Verbinden
|
||||
</button>
|
||||
</div>
|
||||
@@ -112,12 +97,21 @@
|
||||
setTheme(current === 'dark' ? 'light' : 'dark');
|
||||
}
|
||||
|
||||
// Button aktivieren/deaktivieren
|
||||
function updateConnectBtn() {
|
||||
const ssid = document.getElementById('ssid').value;
|
||||
const pw = document.getElementById('password').value;
|
||||
const btn = document.getElementById('connect-btn');
|
||||
btn.disabled = !(ssid.length > 0 && pw.length > 0);
|
||||
}
|
||||
|
||||
// Initialize on load
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initTheme();
|
||||
initI18n();
|
||||
// Auto-scan on load
|
||||
setTimeout(scanNetworks, 500);
|
||||
document.getElementById('ssid').addEventListener('input', updateConnectBtn);
|
||||
document.getElementById('password').addEventListener('input', updateConnectBtn);
|
||||
updateConnectBtn();
|
||||
});
|
||||
|
||||
// Toggle password visibility
|
||||
|
||||
@@ -39,6 +39,15 @@ body {
|
||||
box-shadow: 0 4px 20px var(--shadow);
|
||||
}
|
||||
|
||||
#connect-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
box-shadow: none;
|
||||
background-color: #888 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Form Group - More spacing */
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🚂 System Control</h1>
|
||||
<div class="header-controls">
|
||||
<button class="lang-toggle" onclick="toggleLanguage()" aria-label="Sprache wechseln">
|
||||
<span class="lang-flag" id="lang-flag">🇩🇪</span>
|
||||
@@ -27,6 +26,7 @@
|
||||
<span class="theme-toggle-label" id="theme-label">Dark</span>
|
||||
</button>
|
||||
</div>
|
||||
<h1>🚂 System Control</h1>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
|
||||
@@ -43,6 +43,13 @@ async function scanNetworks() {
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/wifi/scan');
|
||||
if (!response.ok) {
|
||||
// Fehlerhafte API-Antwort, aber ESP32 ist erreichbar
|
||||
const errorText = await response.text();
|
||||
showStatus('wifi-status', t('wifi.error.scan') + ': ' + errorText, 'error');
|
||||
if (loading) loading.classList.remove('active');
|
||||
return;
|
||||
}
|
||||
const networks = await response.json();
|
||||
|
||||
if (loading) {
|
||||
@@ -92,43 +99,43 @@ async function scanNetworks() {
|
||||
if (loading) {
|
||||
loading.classList.remove('active');
|
||||
}
|
||||
|
||||
// Demo mode for local testing
|
||||
const demoNetworks = [
|
||||
{ ssid: 'Demo-Netzwerk', rssi: -45 },
|
||||
{ ssid: 'Gast-WLAN', rssi: -67 },
|
||||
{ ssid: 'Nachbar-WiFi', rssi: -82 }
|
||||
];
|
||||
|
||||
if (networkList) {
|
||||
demoNetworks.forEach(network => {
|
||||
const signalIcon = getSignalIcon(network.rssi);
|
||||
const item = document.createElement('div');
|
||||
item.className = 'network-item';
|
||||
item.onclick = () => selectNetwork(network.ssid, item);
|
||||
item.innerHTML = `
|
||||
<span class="network-name">
|
||||
<span class="signal-icon">${signalIcon}</span>
|
||||
${escapeHtml(network.ssid)}
|
||||
</span>
|
||||
<span class="network-signal">${network.rssi} dBm</span>
|
||||
`;
|
||||
networkList.appendChild(item);
|
||||
});
|
||||
networkList.style.display = 'block';
|
||||
// Nur bei Netzwerkfehlern Demo-Daten anzeigen
|
||||
if (error instanceof TypeError) {
|
||||
const demoNetworks = [
|
||||
{ ssid: 'Demo-Netzwerk', rssi: -45 },
|
||||
{ ssid: 'Gast-WLAN', rssi: -67 },
|
||||
{ ssid: 'Nachbar-WiFi', rssi: -82 }
|
||||
];
|
||||
if (networkList) {
|
||||
demoNetworks.forEach(network => {
|
||||
const signalIcon = getSignalIcon(network.rssi);
|
||||
const item = document.createElement('div');
|
||||
item.className = 'network-item';
|
||||
item.onclick = () => selectNetwork(network.ssid, item);
|
||||
item.innerHTML = `
|
||||
<span class="network-name">
|
||||
<span class="signal-icon">${signalIcon}</span>
|
||||
${escapeHtml(network.ssid)}
|
||||
</span>
|
||||
<span class="network-signal">${network.rssi} dBm</span>
|
||||
`;
|
||||
networkList.appendChild(item);
|
||||
});
|
||||
networkList.style.display = 'block';
|
||||
}
|
||||
if (select) {
|
||||
select.innerHTML = `<option value="">${t('wifi.scan.hint')}</option>`;
|
||||
demoNetworks.forEach(network => {
|
||||
const option = document.createElement('option');
|
||||
option.value = network.ssid;
|
||||
option.textContent = `${network.ssid} (${network.rssi} dBm)`;
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
showStatus('wifi-status', 'Demo: ' + t('wifi.networks.found', { count: demoNetworks.length }), 'info');
|
||||
} else {
|
||||
showStatus('wifi-status', t('wifi.error.scan') + ': ' + error.message, 'error');
|
||||
}
|
||||
|
||||
if (select) {
|
||||
select.innerHTML = `<option value="">${t('wifi.scan.hint')}</option>`;
|
||||
demoNetworks.forEach(network => {
|
||||
const option = document.createElement('option');
|
||||
option.value = network.ssid;
|
||||
option.textContent = `${network.ssid} (${network.rssi} dBm)`;
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
showStatus('wifi-status', 'Demo: ' + t('wifi.networks.found', { count: demoNetworks.length }), 'info');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user