diff --git a/main/maxxfan-controller.c b/main/maxxfan-controller.c
index 91a68e8..5cbf04f 100755
--- a/main/maxxfan-controller.c
+++ b/main/maxxfan-controller.c
@@ -79,127 +79,48 @@ static httpd_handle_t server = NULL;
// Task handles for watchdog
static TaskHandle_t main_task_handle = NULL;
-// HTML web page for control (same as before)
+// Compact HTML web page for control
static const char* html_page =
-""
-""
-"
"
-" Maxxfan Controller "
-" "
-" "
-""
-""
-" "
-"
Maxxfan Controller "
-" "
-"
"
-"
Current Status "
-"
Mode: OFF
"
-"
Speed: 0 %
"
-"
Target: 0 %
"
-"
"
-" Ramping in progress... "
-"
"
-"
"
-" "
-"
"
-"
Fan Control "
-" Turn OFF "
-" Exhaust (50%) "
-" Intake (50%) "
-" "
-" "
-"
"
-"
Speed Control "
-"
"
-" Speed: 50 % "
-" "
-"
"
-"
Set Exhaust Speed "
-"
Set Intake Speed "
-"
"
-"
"
-""
-" "
-""
-"";
+"Maxxfan Maxxfan Controller "
+"
Status Mode: OFF
Speed: 0 %
"
+"
Target: 0 %
Ramping...
"
+"
Error
Connecting... "
+"
Fan Control OFF "
+"Exhaust 50% "
+"Intake 50% "
+"
Speed Control Speed: 50 % "
+" "
+"Set Exhaust "
+"Set Intake "
+"";
// Forward declarations
static void motor_ramp_timer_callback(TimerHandle_t xTimer);
@@ -458,9 +379,18 @@ void set_motor_speed(motor_mode_t mode, int speed_percent)
}
}
+// Helper function to set CORS headers
+static void set_cors_headers(httpd_req_t *req) {
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "GET, POST, OPTIONS");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Headers", "Content-Type, Accept");
+ httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
+}
+
// HTTP handler for the main web page
static esp_err_t root_get_handler(httpd_req_t *req)
{
+ set_cors_headers(req);
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, html_page, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
@@ -469,6 +399,13 @@ static esp_err_t root_get_handler(httpd_req_t *req)
// HTTP handler for fan status (GET /status)
static esp_err_t status_get_handler(httpd_req_t *req)
{
+ ESP_LOGI(TAG, "Status request - Mode: %d, Current: %d%%, Target: %d%%, Ramping: %s",
+ motor_state.mode, motor_state.current_speed, motor_state.target_speed,
+ motor_state.ramping ? "YES" : "NO");
+
+ set_cors_headers(req);
+ httpd_resp_set_type(req, "application/json");
+
cJSON *json = cJSON_CreateObject();
const char* mode_str = "off";
@@ -481,10 +418,13 @@ static esp_err_t status_get_handler(httpd_req_t *req)
cJSON_AddBoolToObject(json, "ramping", motor_state.ramping);
char *json_string = cJSON_Print(json);
- httpd_resp_set_type(req, "application/json");
- httpd_resp_send(req, json_string, strlen(json_string));
+ if (json_string) {
+ httpd_resp_send(req, json_string, strlen(json_string));
+ free(json_string);
+ } else {
+ httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "JSON creation failed");
+ }
- free(json_string);
cJSON_Delete(json);
return ESP_OK;
}
@@ -492,7 +432,7 @@ static esp_err_t status_get_handler(httpd_req_t *req)
// HTTP handler for fan control (POST /fan)
static esp_err_t fan_post_handler(httpd_req_t *req)
{
- char buf[100];
+ char buf[200];
int ret, remaining = req->content_len;
if (remaining >= sizeof(buf)) {
@@ -509,8 +449,11 @@ static esp_err_t fan_post_handler(httpd_req_t *req)
}
buf[ret] = '\0';
+ ESP_LOGI(TAG, "Received POST data: %s", buf);
+
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
+ ESP_LOGE(TAG, "JSON parsing failed");
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
@@ -551,20 +494,32 @@ static esp_err_t fan_post_handler(httpd_req_t *req)
cJSON_Delete(json);
- // Send response
+ // Send response with updated status
return status_get_handler(req);
}
+// HTTP handler for OPTIONS requests (CORS preflight)
+static esp_err_t options_handler(httpd_req_t *req)
+{
+ set_cors_headers(req);
+ httpd_resp_set_status(req, "200 OK");
+ httpd_resp_send(req, NULL, 0);
+ return ESP_OK;
+}
+
// Start HTTP server
static httpd_handle_t start_webserver(void)
{
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
- config.max_uri_handlers = 10;
+ config.max_uri_handlers = 15;
+ config.recv_wait_timeout = 10;
+ config.send_wait_timeout = 10;
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK) {
ESP_LOGI(TAG, "Registering URI handlers");
+ // Root handler
httpd_uri_t root = {
.uri = "/",
.method = HTTP_GET,
@@ -573,6 +528,7 @@ static httpd_handle_t start_webserver(void)
};
httpd_register_uri_handler(server, &root);
+ // Status handler
httpd_uri_t status = {
.uri = "/status",
.method = HTTP_GET,
@@ -581,6 +537,7 @@ static httpd_handle_t start_webserver(void)
};
httpd_register_uri_handler(server, &status);
+ // Fan control handler
httpd_uri_t fan = {
.uri = "/fan",
.method = HTTP_POST,
@@ -589,6 +546,23 @@ static httpd_handle_t start_webserver(void)
};
httpd_register_uri_handler(server, &fan);
+ // OPTIONS handler for CORS preflight
+ httpd_uri_t options_status = {
+ .uri = "/status",
+ .method = HTTP_OPTIONS,
+ .handler = options_handler,
+ .user_ctx = NULL
+ };
+ httpd_register_uri_handler(server, &options_status);
+
+ httpd_uri_t options_fan = {
+ .uri = "/fan",
+ .method = HTTP_OPTIONS,
+ .handler = options_handler,
+ .user_ctx = NULL
+ };
+ httpd_register_uri_handler(server, &options_fan);
+
return server;
}
@@ -691,7 +665,7 @@ void app_main(void)
start_webserver();
ESP_LOGI(TAG, "=== Enhanced Maxxfan Controller Ready! ===");
- ESP_LOGI(TAG, "Features: Motor Ramping, Optimized Performance");
+ ESP_LOGI(TAG, "Features: Motor Ramping, Optimized Performance, Real-time Updates");
ESP_LOGI(TAG, "Open your browser and go to: http://[ESP32_IP_ADDRESS]");
ESP_LOGI(TAG, "Check the monitor output above for your IP address");