#include "webserver.h" #include "esp_event.h" #include "esp_http_server.h" #include "esp_log.h" #include "esp_mac.h" #include "esp_system.h" #include "esp_wifi.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "nvs_flash.h" #include #include #include #define AP_WIFI_SSID "AutoSpa" #define AP_WIFI_PASS "autospa123" #define AP_MAX_CONN 4 #define AP_WIFI_CHANNEL 1 #define STA_WIFI_SSID "Big_Blue_House" #define STA_WIFI_PASS "tDMiar*2024" static const char *TAG = "webserver"; static volatile int s_check_id_req = 0; // Log buffer #define LOG_BUF_SIZE 4096 static char log_buffer[LOG_BUF_SIZE]; static int log_head = 0; void web_log(const char *fmt, ...) { va_list args; va_start(args, fmt); char temp[256]; int len = vsnprintf(temp, sizeof(temp), fmt, args); va_end(args); if (len > 0) { if (log_head + len < LOG_BUF_SIZE - 1) { memcpy(log_buffer + log_head, temp, len); log_head += len; log_buffer[log_head] = '\0'; } else { log_head = 0; memcpy(log_buffer + log_head, temp, len); log_head += len; log_buffer[log_head] = '\0'; } ESP_LOGI(TAG, "%s", temp); } } int check_id_requested(void) { if (s_check_id_req) { s_check_id_req = 0; return 1; } return 0; } /* WiFi AP Event Handler */ /* WiFi Event Handler */ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) { wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data; ESP_LOGI(TAG, "station " MACSTR " joined, AID=%d", MAC2STR(event->mac), event->aid); web_log("Client connected!\n"); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) { wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data; ESP_LOGI(TAG, "station " MACSTR " left, AID=%d", MAC2STR(event->mac), event->aid); web_log("Client disconnected.\n"); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); ESP_LOGI(TAG, "retry to connect to the AP"); web_log("Retry to connect to the AP\n"); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); web_log("Got IP: " IPSTR "\n", IP2STR(&event->ip_info.ip)); start_webserver(); } } void wifi_init_ap(void) { ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); 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_event_handler_instance_register( WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL)); wifi_config_t wifi_config = { .ap = { .ssid = AP_WIFI_SSID, .ssid_len = strlen(AP_WIFI_SSID), .channel = AP_WIFI_CHANNEL, .password = AP_WIFI_PASS, .max_connection = AP_MAX_CONN, .authmode = WIFI_AUTH_WPA2_PSK, .pmf_cfg = {.required = true}, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "SoftAP started. SSID: %s, Password: %s", AP_WIFI_SSID, AP_WIFI_PASS); ESP_LOGI(TAG, "Connect to this WiFi and browse to http://192.168.4.1:9099"); } void wifi_init_sta(void) { ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_event_handler_instance_register( WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL)); ESP_ERROR_CHECK(esp_event_handler_instance_register( IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL)); wifi_config_t wifi_config = { .sta = { .ssid = STA_WIFI_SSID, .password = STA_WIFI_PASS, /* Setting a password implies station will connect to all security * modes including WEP/WPA. However these modes are deprecated and * not advised to be used. Incase your Access point doesn't * support WPA2, these mode can be enabled by commenting below * line */ .threshold.authmode = WIFI_AUTH_WPA2_PSK, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "wifi_init_sta finished."); } /* HTTP Server Handlers */ static const char *index_html = "AD5940 Control" "

AD5940 ESP32-S3 Dashboard

" "" "

Console Log

" "
"
    "";

static esp_err_t root_get_handler(httpd_req_t *req) {
  ESP_LOGI(TAG, "Request received for %s", req->uri);
  httpd_resp_send(req, index_html, HTTPD_RESP_USE_STRLEN);
  return ESP_OK;
}

static esp_err_t command_post_handler(httpd_req_t *req) {
  char buf[100];
  int ret, remaining = req->content_len;

  if (remaining >= sizeof(buf)) {
    remaining = sizeof(buf) - 1;
  }

  ret = httpd_req_recv(req, buf, remaining);
  if (ret <= 0)
    return ESP_FAIL;
  buf[ret] = '\0';

  if (strstr(buf, "check_id")) {
    s_check_id_req = 1;
    web_log("Command received: Check ID\n");
  }

  httpd_resp_send(req, "OK", HTTPD_RESP_USE_STRLEN);
  return ESP_OK;
}

static esp_err_t log_get_handler(httpd_req_t *req) {
  httpd_resp_set_type(req, "text/plain");
  httpd_resp_send(req, log_buffer, HTTPD_RESP_USE_STRLEN);
  // Note: This sends the whole buffer every time.
  // Optimization: implement cursor or clear on read.
  // For now, this is enough for "Check ID" simple verification.
  return ESP_OK;
}

void start_webserver(void) {
  httpd_handle_t server = NULL;
  httpd_config_t config = HTTPD_DEFAULT_CONFIG();
  config.server_port = 9099;
  config.lru_purge_enable = true;

  ESP_LOGI(TAG, "Starting web server"); // Log to serial for debug too
  if (httpd_start(&server, &config) == ESP_OK) {
    ESP_LOGI(TAG, "Web server started on port %d", config.server_port);
    httpd_uri_t root = {.uri = "/",
                        .method = HTTP_GET,
                        .handler = root_get_handler,
                        .user_ctx = NULL};
    httpd_register_uri_handler(server, &root);

    httpd_uri_t cmd = {.uri = "/api/command",
                       .method = HTTP_POST,
                       .handler = command_post_handler,
                       .user_ctx = NULL};
    httpd_register_uri_handler(server, &cmd);

    httpd_uri_t log_uri = {.uri = "/api/log",
                           .method = HTTP_GET,
                           .handler = log_get_handler,
                           .user_ctx = NULL};
    httpd_register_uri_handler(server, &log_uri);
  } else {
    ESP_LOGE(TAG, "Error starting server!");
  }
}