/ src / web / server.rs
server.rs
  1  /// HTTP server initialization and routing
  2  use anyhow::Result;
  3  use esp_idf_svc::http::server::{Configuration, EspHttpServer};
  4  use log::info;
  5  use std::sync::Arc;
  6  
  7  use super::handlers::*;
  8  use super::state::WebServerState;
  9  
 10  /// Initialize and start the HTTP server
 11  pub fn start_web_server(state: Arc<WebServerState>) -> Result<EspHttpServer<'static>> {
 12      let config = Configuration {
 13          stack_size: 10240, // Increased from 8192 for safer operation with complex handlers
 14          max_sessions: 5,   // Increased from 3 to allow more concurrent users
 15          max_open_sockets: 5, // Match max_sessions for optimal performance
 16          ..Default::default()
 17      };
 18  
 19      let mut server = EspHttpServer::new(&config)?;
 20  
 21      // Clone state for each handler
 22      let state_login_get = state.clone();
 23      let state_login_post = state.clone();
 24      let state_admin = state.clone();
 25      let state_update = state.clone();
 26      let state_logout = state.clone();
 27      let state_reboot = state.clone();
 28      let state_relay_on = state.clone();
 29      let state_relay_off = state.clone();
 30      let state_ota_check = state.clone();
 31      let state_ota_upload = state.clone();
 32      let state_stats_api = state.clone();
 33      let state_alarm_clear = state.clone();
 34      let state_download_settings = state.clone();
 35      let state_upload_settings = state.clone();
 36  
 37      // Route: GET /
 38      server.fn_handler("/", embedded_svc::http::Method::Get, move |req| {
 39          redirect_to_admin(req)
 40      })?;
 41  
 42      // Route: GET /login
 43      server.fn_handler("/login", embedded_svc::http::Method::Get, move |req| {
 44          handle_login_page(req, &state_login_get, None)
 45      })?;
 46  
 47      // Route: POST /login
 48      server.fn_handler("/login", embedded_svc::http::Method::Post, move |req| {
 49          handle_login_submit(req, &state_login_post)
 50      })?;
 51  
 52      // Route: GET /admin
 53      server.fn_handler("/admin", embedded_svc::http::Method::Get, move |req| {
 54          handle_admin_panel(req, &state_admin, None)
 55      })?;
 56  
 57      // Route: POST /update-settings
 58      server.fn_handler(
 59          "/update-settings",
 60          embedded_svc::http::Method::Post,
 61          move |req| handle_update_settings(req, &state_update),
 62      )?;
 63  
 64      // Route: GET /logout
 65      server.fn_handler("/logout", embedded_svc::http::Method::Get, move |req| {
 66          handle_logout(req, &state_logout)
 67      })?;
 68  
 69      // Route: GET /reboot
 70      server.fn_handler("/reboot", embedded_svc::http::Method::Get, move |req| {
 71          handle_reboot(req, &state_reboot)
 72      })?;
 73  
 74      // Route: POST /relay/on
 75      server.fn_handler("/relay/on", embedded_svc::http::Method::Post, move |req| {
 76          handle_relay_control(req, &state_relay_on, true)
 77      })?;
 78  
 79      // Route: POST /relay/off
 80      server.fn_handler("/relay/off", embedded_svc::http::Method::Post, move |req| {
 81          handle_relay_control(req, &state_relay_off, false)
 82      })?;
 83  
 84      // Route: GET /ota/check - Check for OTA updates
 85      server.fn_handler("/ota/check", embedded_svc::http::Method::Get, move |req| {
 86          handle_ota_check(req, &state_ota_check)
 87      })?;
 88  
 89      // Route: POST /ota/upload - Upload firmware
 90      server.fn_handler(
 91          "/ota/upload",
 92          embedded_svc::http::Method::Post,
 93          move |req| handle_ota_upload(req, &state_ota_upload),
 94      )?;
 95  
 96      // Route: GET /api/stats - Live statistics JSON API
 97      server.fn_handler("/api/stats", embedded_svc::http::Method::Get, move |req| {
 98          handle_stats_api(req, &state_stats_api)
 99      })?;
100  
101      // Route: POST /alarm/clear - Clear all alarm conditions
102      server.fn_handler(
103          "/alarm/clear",
104          embedded_svc::http::Method::Post,
105          move |req| handle_alarm_clear(req, &state_alarm_clear),
106      )?;
107  
108      // Route: GET /download-settings - Download settings as TOML file
109      server.fn_handler(
110          "/download-settings",
111          embedded_svc::http::Method::Get,
112          move |req| handle_download_settings(req, &state_download_settings),
113      )?;
114  
115      // Route: POST /upload-settings - Upload and restore settings from TOML file
116      server.fn_handler(
117          "/upload-settings",
118          embedded_svc::http::Method::Post,
119          move |req| handle_upload_settings(req, &state_upload_settings),
120      )?;
121  
122      // New advanced device management endpoints
123      let state_device_status = state.clone();
124      let state_ota_rollback = state.clone();
125      let state_ota_mark_valid = state.clone();
126  
127      // Route: GET /api/device/status - Get device diagnostics
128      server.fn_handler(
129          "/api/device/status",
130          embedded_svc::http::Method::Get,
131          move |req| handle_device_status(req, &state_device_status),
132      )?;
133  
134      // Route: POST /api/ota/rollback - Rollback to previous firmware
135      server.fn_handler(
136          "/api/ota/rollback",
137          embedded_svc::http::Method::Post,
138          move |req| handle_ota_rollback(req, &state_ota_rollback),
139      )?;
140  
141      // Route: POST /api/ota/mark-valid - Mark current firmware as valid
142      server.fn_handler(
143          "/api/ota/mark-valid",
144          embedded_svc::http::Method::Post,
145          move |req| handle_ota_mark_valid(req, &state_ota_mark_valid),
146      )?;
147  
148      info!("Web server started successfully");
149      Ok(server)
150  }