Files
maxxfan-controller/main/maxxfan-controller.c

208 lines
8.5 KiB
C
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "nvs.h"
// Project modules
#include "config.h"
#include "motor_control.h"
#include "state_manager.h"
#include "wifi_manager.h"
#include "http_server.h"
// Task handles for watchdog
static TaskHandle_t main_task_handle = NULL;
// Initialize watchdog timer
void init_watchdog(void) {
ESP_LOGI(SYSTEM_TAG, "Setting up watchdog monitoring...");
// Get current task handle and add to watchdog
main_task_handle = xTaskGetCurrentTaskHandle();
esp_err_t result = esp_task_wdt_add(main_task_handle);
if (result == ESP_OK) {
ESP_LOGI(SYSTEM_TAG, "Main task added to watchdog monitoring");
} else if (result == ESP_ERR_INVALID_ARG) {
ESP_LOGI(SYSTEM_TAG, "Task already monitored by watchdog");
} else {
ESP_LOGW(SYSTEM_TAG, "Watchdog not available: %s", esp_err_to_name(result));
main_task_handle = NULL; // Disable watchdog feeding
}
}
// Feed the watchdog
void feed_watchdog(void) {
if (main_task_handle != NULL) {
esp_err_t result = esp_task_wdt_reset();
if (result != ESP_OK) {
MOTOR_LOGD(SYSTEM_TAG, "Watchdog reset failed: %s", esp_err_to_name(result));
}
}
}
void app_main(void)
{
ESP_LOGI(SYSTEM_TAG, "Starting Maxxfan HTTP Controller with State Preservation!");
// Initialize state manager (includes NVS initialization)
ESP_LOGI(SYSTEM_TAG, "Initializing state manager...");
esp_err_t ret = state_manager_init();
if (ret != ESP_OK) {
ESP_LOGE(SYSTEM_TAG, "Failed to initialize state manager: %s", esp_err_to_name(ret));
return;
}
// Initialize watchdog timer
init_watchdog();
// Initialize motor control system
ESP_LOGI(SYSTEM_TAG, "Initializing motor control system...");
ret = motor_control_init();
if (ret != ESP_OK) {
ESP_LOGE(SYSTEM_TAG, "Failed to initialize motor control: %s", esp_err_to_name(ret));
return;
}
// Load saved state and restore motor if appropriate
ESP_LOGI(SYSTEM_TAG, "Loading saved state and applying restoration logic...");
esp_err_t load_result = state_manager_load_and_restore();
if (load_result == ESP_OK) {
ESP_LOGI(SYSTEM_TAG, "✓ State loaded and restoration logic applied");
} else if (load_result == ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGI(SYSTEM_TAG, " No saved state found, using defaults");
} else {
ESP_LOGW(SYSTEM_TAG, "⚠️ Failed to load state: %s", esp_err_to_name(load_result));
}
// Initialize WiFi manager
ESP_LOGI(SYSTEM_TAG, "Initializing WiFi manager...");
ret = wifi_manager_init();
if (ret != ESP_OK) {
ESP_LOGE(SYSTEM_TAG, "Failed to initialize WiFi manager: %s", esp_err_to_name(ret));
return;
}
// Connect to WiFi using default credentials
ESP_LOGI(SYSTEM_TAG, "Connecting to WiFi network: %s", WIFI_SSID);
ret = wifi_manager_connect_default();
if (ret != ESP_OK) {
ESP_LOGE(SYSTEM_TAG, "Failed to start WiFi connection: %s", esp_err_to_name(ret));
return;
}
// Wait for WiFi connection (with timeout)
ESP_LOGI(SYSTEM_TAG, "Waiting for WiFi connection...");
esp_err_t wifi_result = wifi_manager_wait_for_connection(30000); // 30 second timeout
if (wifi_result == ESP_OK) {
char ip_str[16];
wifi_manager_get_ip_string(ip_str, sizeof(ip_str));
wifi_info_t wifi_info;
wifi_manager_get_info(&wifi_info);
ESP_LOGI(SYSTEM_TAG, "✓ WiFi connected successfully!");
ESP_LOGI(SYSTEM_TAG, " SSID: %s", wifi_info.ssid);
ESP_LOGI(SYSTEM_TAG, " IP Address: %s", ip_str);
ESP_LOGI(SYSTEM_TAG, " Signal Strength: %d dBm", wifi_info.rssi);
} else if (wifi_result == ESP_ERR_TIMEOUT) {
ESP_LOGW(SYSTEM_TAG, "⚠️ WiFi connection timeout - continuing with limited functionality");
} else {
ESP_LOGW(SYSTEM_TAG, "⚠️ WiFi connection failed - continuing with limited functionality");
}
// Start HTTP server (even if WiFi failed, for debugging)
ESP_LOGI(SYSTEM_TAG, "Starting web server...");
ret = http_server_init();
if (ret == ESP_OK) {
ESP_LOGI(SYSTEM_TAG, "✓ Web server started successfully");
} else {
ESP_LOGE(SYSTEM_TAG, "✗ Failed to start web server: %s", esp_err_to_name(ret));
}
// Report final system state after initialization
const motor_state_t* final_state = motor_get_state();
wifi_info_t final_wifi_info;
wifi_manager_get_info(&final_wifi_info);
char final_ip_str[16];
wifi_manager_get_ip_string(final_ip_str, sizeof(final_ip_str));
ESP_LOGI(SYSTEM_TAG, "=== SYSTEM INITIALIZATION COMPLETE ===");
ESP_LOGI(SYSTEM_TAG, "Reset Reason: %s", state_manager_get_reset_reason_string());
ESP_LOGI(SYSTEM_TAG, "Watchdog Reset: %s", state_manager_was_watchdog_reset() ? "YES" : "NO");
// Motor status
ESP_LOGI(SYSTEM_TAG, "Motor: mode=%s, target=%d%%, current=%d%%, state=%s",
motor_mode_to_string(final_state->mode), final_state->target_speed,
final_state->current_speed, motor_state_to_string(final_state->state));
if (final_state->mode != MOTOR_OFF && final_state->target_speed > 0) {
ESP_LOGI(SYSTEM_TAG, "🔄 Motor restored to: %s @ %d%%",
motor_mode_to_string(final_state->mode), final_state->target_speed);
} else {
ESP_LOGI(SYSTEM_TAG, "⏸️ Motor remains OFF");
}
motor_mode_t last_on_mode;
int last_on_speed;
motor_get_last_on_state(&last_on_mode, &last_on_speed);
ESP_LOGI(SYSTEM_TAG, "Last ON state: %s @ %d%%",
motor_mode_to_string(last_on_mode), last_on_speed);
ESP_LOGI(SYSTEM_TAG, "User turned off: %s", motor_get_user_turned_off() ? "YES" : "NO");
// WiFi status
ESP_LOGI(SYSTEM_TAG, "WiFi: status=%s, SSID=%s, IP=%s, RSSI=%d dBm",
wifi_manager_status_to_string(final_wifi_info.status),
final_wifi_info.ssid, final_ip_str, final_wifi_info.rssi);
// Connection statistics
uint32_t total_attempts, successful_connections;
esp_err_t last_wifi_error;
wifi_manager_get_stats(&total_attempts, &successful_connections, &last_wifi_error);
ESP_LOGI(SYSTEM_TAG, "WiFi Stats: %lu attempts, %lu successful", total_attempts, successful_connections);
// HTTP server statistics
uint32_t total_requests, active_connections, last_request_time;
http_server_get_stats(&total_requests, &active_connections, &last_request_time);
ESP_LOGI(SYSTEM_TAG, "HTTP Server: running=%s, requests=%lu",
http_server_is_running() ? "YES" : "NO", total_requests);
ESP_LOGI(SYSTEM_TAG, "Saved state exists: %s", state_manager_has_saved_state() ? "YES" : "NO");
ESP_LOGI(SYSTEM_TAG, "=====================================");
ESP_LOGI(SYSTEM_TAG, "=== Enhanced Maxxfan Controller Ready! ===");
ESP_LOGI(SYSTEM_TAG, "Features: State Preservation, Direction Safety, Motor Ramping, ON Button");
ESP_LOGI(SYSTEM_TAG, "Safety: %d-second cooldown for direction changes", DIRECTION_CHANGE_COOLDOWN_MS / 1000);
ESP_LOGI(SYSTEM_TAG, "Memory: Remembers settings after power loss (except watchdog resets)");
ESP_LOGI(SYSTEM_TAG, "WiFi: Enhanced connection management with auto-reconnect");
ESP_LOGI(SYSTEM_TAG, "State Manager: Enhanced NVS operations with validation and recovery");
ESP_LOGI(SYSTEM_TAG, "HTTP Server: Modular web server with comprehensive API");
if (wifi_manager_is_connected()) {
ESP_LOGI(SYSTEM_TAG, "🌐 Open your browser and go to: http://%s", final_ip_str);
} else {
ESP_LOGI(SYSTEM_TAG, "⚠️ WiFi not connected - check network settings");
}
// Main loop - reset watchdog periodically and update motor cooldown
uint32_t loop_count = 0;
while (1) {
feed_watchdog();
// Update motor cooldown time for status reporting
motor_update_cooldown_time();
// Periodic WiFi status logging (every 30 seconds)
if (++loop_count % 10 == 0) {
wifi_status_t current_status = wifi_manager_get_status();
if (current_status != WIFI_STATUS_CONNECTED) {
ESP_LOGW(SYSTEM_TAG, "WiFi status: %s", wifi_manager_status_to_string(current_status));
}
}
vTaskDelay(pdMS_TO_TICKS(WATCHDOG_FEED_INTERVAL_MS));
}
}