項目描述:
本項目采用485采集溫濕度以及電壓電流等,485模塊分別為下圖,串口轉485模塊采用自動收發模塊,ESP32工作在AP熱點模式,通過手機連接esp32的熱點來和esp進行數據通訊,
使用esp32作為HTTP服務器
缺陷:
項目的最終HTML頁面
代碼
可發給AI讓其寫注釋
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>
#include "lwip/err.h"
#include "lwip/sys.h"
#include <esp_http_server.h>
#include <stdio.h>
#include <string.h>
#include "freertos/queue.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "cJSON.h"
#include <time.h>/* 配置參數 */
#define EXAMPLE_ESP_WIFI_SSID "laotie666"
#define EXAMPLE_ESP_WIFI_PASS "12345678"
#define EXAMPLE_ESP_WIFI_CHANNEL 1
#define EXAMPLE_MAX_STA_CONN 4
#define EXAMPLE_HTTP_QUERY_KEY_MAX_LEN (64)#define EX_UART_NUM UART_NUM_1
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)/* 全局變量 */
uint8_t get_jsy_value[8] = {0x02, 0x03, 0x00, 0x48, 0x00, 0x05, 0x05, 0xEC};
uint8_t get_val[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};
uint16_t Hum = 255; // 濕度值 Hum = 實際值 * 10
int16_t Tem = 232; // 溫度值 Tem = 實際值 * 10
uint16_t Voltage=24, Current=2;
float Power=2.3; // 功率static QueueHandle_t uart0_queue;
static const char *TAG = "wifi softAP";/* 美觀的HTML頁面模板 */
static const char *HTML_PAGE = R"rawliteral(
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ESP32 環境監測</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);min-height: 100vh;display: flex;justify-content: center;align-items: center;padding: 20px;}.container {background: rgba(255, 255, 255, 0.15);backdrop-filter: blur(10px);border-radius: 20px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);width: 100%;max-width: 500px;padding: 30px;color: white;}header {text-align: center;margin-bottom: 30px;}h1 {font-size: 28px;margin-bottom: 10px;text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);}.status {display: flex;align-items: center;justify-content: center;gap: 10px;font-size: 16px;}.status-indicator {width: 12px;height: 12px;border-radius: 50%;background-color: #4CAF50;box-shadow: 0 0 10px #4CAF50;}.sensors-grid {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;margin-bottom: 30px;}.sensor-card {background: rgba(255, 255, 255, 0.1);border-radius: 15px;padding: 20px;text-align: center;transition: transform 0.3s ease, box-shadow 0.3s ease;cursor: pointer;}.sensor-card:hover {transform: translateY(-5px);box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2);background: rgba(255, 255, 255, 0.2);}.sensor-icon {font-size: 40px;margin-bottom: 15px;}.sensor-value {font-size: 32px;font-weight: bold;margin: 10px 0;}.sensor-unit {font-size: 16px;opacity: 0.8;}.sensor-title {font-size: 18px;margin-bottom: 10px;color: #FFD700;}.power-section {background: rgba(0, 0, 0, 0.2);border-radius: 15px;padding: 20px;margin-bottom: 25px;}.power-title {text-align: center;font-size: 20px;margin-bottom: 15px;color: #FFD700;}.power-grid {display: grid;grid-template-columns: repeat(3, 1fr);gap: 15px;}.power-card {background: rgba(255, 255, 255, 0.1);border-radius: 10px;padding: 15px;text-align: center;}.power-value {font-size: 24px;font-weight: bold;margin: 5px 0;}.power-label {font-size: 14px;opacity: 0.8;}.last-update {text-align: center;font-size: 14px;opacity: 0.7;margin-top: 20px;}.refresh-info {text-align: center;font-size: 14px;margin-top: 10px;opacity: 0.7;}footer {text-align: center;margin-top: 30px;font-size: 14px;opacity: 0.8;}</style>
</head>
<body><div class="container"><header><h1>ESP32 環境監測</h1><div class="status"><div class="status-indicator"></div><span>設備在線</span></div></header><div class="sensors-grid"><div class="sensor-card" style="border: 2px solid #FF5252;"><div class="sensor-icon">🌡?</div><div class="sensor-title">溫度</div><div class="sensor-value">%.1f</div><div class="sensor-unit">°C</div></div><div class="sensor-card" style="border: 2px solid #29B6F6;"><div class="sensor-icon">💧</div><div class="sensor-title">濕度</div><div class="sensor-value">%.1f</div><div class="sensor-unit">%</div></div></div><div class="power-section"><div class="power-title">電能參數</div><div class="power-grid"><div class="power-card"><div class="power-label">電壓</div><div class="power-value">%d</div><div class="power-unit">V</div></div><div class="power-card"><div class="power-label">電流</div><div class="power-value">%.1f</div><div class="power-unit">A</div></div><div class="power-card"><div class="power-label">功率</div><div class="power-value">%.1f</div><div class="power-unit">W</div></div></div></div><div class="last-update">最后更新: %s</div><div class="refresh-info">頁面每2秒自動刷新</div><footer>ESP32 環境監測系統 | ? 2025</footer></div><script>// 每2秒自動刷新頁面setTimeout(function() {location.reload();}, 2000);</script>
</body>
</html>
)rawliteral";/* 獲取當前時間字符串 */
static const char *get_current_time() {static char time_str[20];time_t now = time(NULL);struct tm *timeinfo = localtime(&now);strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo);return time_str;
}/* UART事件處理任務 */
static void uart_event_task(void *pvParameters) {uart_event_t event;size_t buffered_size;uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);for (;;) {if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {bzero(dtmp, RD_BUF_SIZE);switch (event.type) {case UART_DATA:uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);if (event.size == 15) {Voltage = dtmp[3];Voltage = Voltage << 8;Voltage |= dtmp[4];Current = dtmp[5];Current = Current << 8;Current |= dtmp[6];Power = (Voltage * Current) / 10.0f;ESP_LOGI(TAG, "電能數據: %dV, %.1fA, %.1fW", Voltage, Current / 10.0f, Power);} else if (event.size == 9) {Hum = dtmp[3];Hum = Hum << 8;Hum |= dtmp[4];Tem = dtmp[5];Tem = Tem << 8;Tem |= dtmp[6];ESP_LOGI(TAG, "溫濕度數據: %.1f°C, %.1f%%", Tem / 10.0f, Hum / 10.0f);}break;case UART_FIFO_OVF:ESP_LOGW(TAG, "UART FIFO溢出");uart_flush_input(EX_UART_NUM);xQueueReset(uart0_queue);break;case UART_BUFFER_FULL:ESP_LOGW(TAG, "UART緩沖區滿");uart_flush_input(EX_UART_NUM);xQueueReset(uart0_queue);break;case UART_BREAK:ESP_LOGW(TAG, "UART線路斷開");break;case UART_FRAME_ERR:ESP_LOGW(TAG, "UART幀錯誤");break;default:ESP_LOGW(TAG, "未知UART事件: %d", event.type);break;}}}free(dtmp);vTaskDelete(NULL);
}/* 串口發送任務 */
void uart_T_task(void *p) {while (1) {uart_write_bytes(EX_UART_NUM, get_jsy_value, 8);vTaskDelay(pdMS_TO_TICKS(300));uart_write_bytes(EX_UART_NUM, get_val, 8);vTaskDelay(pdMS_TO_TICKS(300));}
}/* WiFi事件處理 */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data) {if (event_id == WIFI_EVENT_AP_STACONNECTED) {wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;ESP_LOGI(TAG, "設備連接: "MACSTR", AID=%d", MAC2STR(event->mac), event->aid);} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;ESP_LOGI(TAG, "設備斷開: "MACSTR", AID=%d, 原因=%d", MAC2STR(event->mac), event->aid, event->reason);}
}/* 初始化WiFi AP */
void wifi_init_softap(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 = EXAMPLE_ESP_WIFI_SSID,.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.password = EXAMPLE_ESP_WIFI_PASS,.max_connection = EXAMPLE_MAX_STA_CONN,.authmode = WIFI_AUTH_WPA2_PSK,.pmf_cfg = {.required = true,},},};if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {wifi_config.ap.authmode = WIFI_AUTH_OPEN;}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, "WiFi AP啟動完成. SSID:%s 密碼:%s 信道:%d",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}/* HTTP請求處理函數:處理根路徑"/"的GET請求,返回帶實時數據的HTML頁面 */
static esp_err_t root_get_handler(httpd_req_t *req) {// 分配內存存儲HTML內容(長度為模板長度+200,預留數據填充空間)char *html_content = (char *)malloc(strlen(HTML_PAGE) + 200);if (!html_content) {// 若內存分配失敗httpd_resp_send_500(req);// 發送500(服務器內部錯誤)響應return ESP_FAIL; // 返回失敗}// 格式化HTML內容,將實時數據填充到HTML代碼模板的占位符中snprintf(html_content, strlen(HTML_PAGE) + 200, HTML_PAGE, Tem / 10.0f, // 溫度(實際值 = 存儲值/10)Hum / 10.0f,// 濕度(實際值 = 存儲值/10)Voltage,// 電壓Current / 10.0f, // 電流(實際值 = 存儲值/10)Power,// 功率get_current_time());// 返回最后更新時間(字符串)// 發送HTTP響應httpd_resp_set_type(req, "text/html");httpd_resp_send(req, html_content, strlen(html_content));free(html_content); // 釋放內存return ESP_OK;
}/* HTTP服務器URI配置:定義根路徑"/"的處理規則 */
static httpd_uri_t root = {.uri = "/",// 匹配的URI路徑.method = HTTP_GET,// 支持的HTTP方法(GET).handler = root_get_handler,//GET方法的 處理函數.user_ctx = NULL // 用戶上下文數據(無)
};/* 啟動HTTP服務器 */
static httpd_handle_t start_webserver(void) {httpd_handle_t server = NULL; // 服務器句柄httpd_config_t config = HTTPD_DEFAULT_CONFIG();// 默認服務器配置config.lru_purge_enable = true; // 啟用LRU(最近最少使用)緩存清理// 啟動HTTP服務器if (httpd_start(&server, &config) == ESP_OK) {// 注冊根路徑"/"的處理函數httpd_register_uri_handler(server, &root);ESP_LOGI(TAG, "HTTP服務器已啟動,端口: %d", config.server_port);return server;}ESP_LOGE(TAG, "HTTP服務器啟動失敗!");return NULL;
}void app_main(void) {// 初始化NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);// 初始化UARTuart_config_t uart_config = {.baud_rate = 9600,.data_bits = UART_DATA_8_BITS,.parity = UART_PARITY_DISABLE,.stop_bits = UART_STOP_BITS_1,.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,.source_clk = UART_SCLK_DEFAULT,};uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);uart_param_config(EX_UART_NUM, &uart_config);uart_set_pin(EX_UART_NUM, GPIO_NUM_4, GPIO_NUM_5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);// 創建任務xTaskCreate(uart_event_task, "uart_event_task", 4046, NULL, 12, NULL);xTaskCreate(uart_T_task, "uart_T_task", 4046, NULL, 10, NULL);// 初始化時間setenv("TZ", "CST-8", 1);tzset();// 初始化WiFi和HTTP服務器ESP_LOGI(TAG, "初始化WiFi AP...");wifi_init_softap();ESP_LOGI(TAG, "啟動HTTP服務器...");httpd_handle_t server = start_webserver();ESP_LOGI(TAG, "系統已啟動完成");ESP_LOGI(TAG, "請連接熱點: %s", EXAMPLE_ESP_WIFI_SSID);ESP_LOGI(TAG, "然后在瀏覽器訪問: http://192.168.4.1");
}
上述代碼時間顯示有問題,下面是優化后的代碼 顯示時間為手機的時間與esp32無關
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>
#include "lwip/err.h"
#include "lwip/sys.h"
#include <esp_http_server.h>
#include <stdio.h>
#include <string.h>
#include "freertos/queue.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "cJSON.h"
#include <time.h>
#include "esp_sntp.h"/* 配置參數 */
#define EXAMPLE_ESP_WIFI_SSID "laotie666"
#define EXAMPLE_ESP_WIFI_PASS "12345678"
#define EXAMPLE_ESP_WIFI_CHANNEL 1
#define EXAMPLE_MAX_STA_CONN 4
#define EXAMPLE_HTTP_QUERY_KEY_MAX_LEN (64)#define EX_UART_NUM UART_NUM_1
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)/* 全局變量 */
uint8_t get_jsy_value[8] = {0x02, 0x03, 0x00, 0x48, 0x00, 0x05, 0x05, 0xEC};
uint8_t get_val[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};
uint16_t Hum = 255; // 濕度值 Hum = 實際值 * 10
int16_t Tem = 232; // 溫度值 Tem = 實際值 * 10
uint16_t Voltage = 24, Current = 2;
float Power = 2.3; // 功率static QueueHandle_t uart0_queue;
static const char *TAG = "wifi softAP";/* 美觀的HTML頁面模板 */
static const char *HTML_PAGE = R"rawliteral(
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ESP32 環境監測</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);min-height: 100vh;display: flex;justify-content: center;align-items: center;padding: 20px;}.container {background: rgba(255, 255, 255, 0.15);backdrop-filter: blur(10px);border-radius: 20px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);width: 100%;max-width: 500px;padding: 30px;color: white;}header {text-align: center;margin-bottom: 30px;}h1 {font-size: 28px;margin-bottom: 10px;text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);}.status {display: flex;align-items: center;justify-content: center;gap: 10px;font-size: 16px;}.status-indicator {width: 12px;height: 12px;border-radius: 50%;background-color: #4CAF50;box-shadow: 0 0 10px #4CAF50;}.sensors-grid {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;margin-bottom: 30px;}.sensor-card {background: rgba(255, 255, 255, 0.1);border-radius: 15px;padding: 20px;text-align: center;transition: transform 0.3s ease, box-shadow 0.3s ease;cursor: pointer;}.sensor-card:hover {transform: translateY(-5px);box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2);background: rgba(255, 255, 255, 0.2);}.sensor-icon {font-size: 40px;margin-bottom: 15px;}.sensor-value {font-size: 32px;font-weight: bold;margin: 10px 0;}.sensor-unit {font-size: 16px;opacity: 0.8;}.sensor-title {font-size: 18px;margin-bottom: 10px;color: #FFD700;}.power-section {background: rgba(0, 0, 0, 0.2);border-radius: 15px;padding: 20px;margin-bottom: 25px;}.power-title {text-align: center;font-size: 20px;margin-bottom: 15px;color: #FFD700;}.power-grid {display: grid;grid-template-columns: repeat(3, 1fr);gap: 15px;}.power-card {background: rgba(255, 255, 255, 0.1);border-radius: 10px;padding: 15px;text-align: center;}.power-value {font-size: 24px;font-weight: bold;margin: 5px 0;}.power-label {font-size: 14px;opacity: 0.8;}.last-update {font-size: 16px;margin-bottom: 8px;color: #FFD700;}#current-time {text-align: center;font-size: 14px;margin-top: 10px;opacity: 0.7;}.refresh-info {text-align: center;font-size: 14px;margin-top: 10px;opacity: 0.7;}footer {text-align: center;margin-top: 30px;font-size: 14px;opacity: 0.8;}</style>
</head>
<body><div class="container"><header><h1>ESP32 環境監測</h1><div class="status"><div class="status-indicator"></div><span>設備在線</span></div></header><div class="sensors-grid"><div class="sensor-card" style="border: 2px solid #FF5252;"><div class="sensor-icon">🌡?</div><div class="sensor-title">溫度</div><div class="sensor-value">%.1f</div><div class="sensor-unit">°C</div></div><div class="sensor-card" style="border: 2px solid #29B6F6;"><div class="sensor-icon">💧</div><div class="sensor-title">濕度</div><div class="sensor-value">%.1f</div><div class="sensor-unit">%%</div></div></div><div class="power-section"><div class="power-title">電能參數</div><div class="power-grid"><div class="power-card"><div class="power-label">電壓</div><div class="power-value">%d</div><div class="power-unit">V</div></div><div class="power-card"><div class="power-label">電流</div><div class="power-value">%.1f</div><div class="power-unit">A</div></div><div class="power-card"><div class="power-label">功率</div><div class="power-value">%.1f</div><div class="power-unit">W</div></div></div></div><div class="refresh-info">數據更新時間: <span id="current-time">正在獲取...</span></div><div class="refresh-info">頁面每秒自動刷新</div><footer>ESP32 環境監測系統 | ? 2025</footer></div><script>
function updateSystemTime() {const now = new Date();const timeString = now.toLocaleString('zh-CN', {year: 'numeric',month: '2-digit',day: '2-digit',hour: '2-digit',minute: '2-digit',second: '2-digit',hour12: false});document.getElementById('current-time').textContent = timeString;
}updateSystemTime();setInterval(updateSystemTime, 1000);setTimeout(function() {location.reload();}, 1000);</script>
</body>
</html>
)rawliteral";/* UART事件處理任務 */
static void uart_event_task(void *pvParameters)
{uart_event_t event;size_t buffered_size;uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);for (;;){if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)){bzero(dtmp, RD_BUF_SIZE);switch (event.type){case UART_DATA:uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);if (event.size == 15){Voltage = dtmp[3];Voltage = Voltage << 8;Voltage |= dtmp[4];Current = dtmp[5];Current = Current << 8;Current |= dtmp[6];Power = (Voltage * Current) / 10.0f;ESP_LOGI(TAG, "電能數據: %dV, %.1fA, %.1fW", Voltage, Current / 10.0f, Power);}else if (event.size == 9){Hum = dtmp[3];Hum = Hum << 8;Hum |= dtmp[4];Tem = dtmp[5];Tem = Tem << 8;Tem |= dtmp[6];ESP_LOGI(TAG, "溫濕度數據: %.1f°C, %.1f%%", Tem / 10.0f, Hum / 10.0f);}break;case UART_FIFO_OVF:ESP_LOGW(TAG, "UART FIFO溢出");uart_flush_input(EX_UART_NUM);xQueueReset(uart0_queue);break;case UART_BUFFER_FULL:ESP_LOGW(TAG, "UART緩沖區滿");uart_flush_input(EX_UART_NUM);xQueueReset(uart0_queue);break;case UART_BREAK:ESP_LOGW(TAG, "UART線路斷開");break;case UART_FRAME_ERR:ESP_LOGW(TAG, "UART幀錯誤");break;default:ESP_LOGW(TAG, "未知UART事件: %d", event.type);break;}}}free(dtmp);vTaskDelete(NULL);
}/* 串口發送任務 */
void uart_T_task(void *p)
{while (1){uart_write_bytes(EX_UART_NUM, get_jsy_value, 8);vTaskDelay(pdMS_TO_TICKS(300));uart_write_bytes(EX_UART_NUM, get_val, 8);vTaskDelay(pdMS_TO_TICKS(300));}
}/* WiFi事件處理 */
static void wifi_event_handler(void *arg, esp_event_base_t event_base,int32_t event_id, void *event_data)
{if (event_id == WIFI_EVENT_AP_STACONNECTED){wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;ESP_LOGI(TAG, "設備連接: " MACSTR ", AID=%d", MAC2STR(event->mac), event->aid);}else if (event_id == WIFI_EVENT_AP_STADISCONNECTED){wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;ESP_LOGI(TAG, "設備斷開: " MACSTR ", AID=%d, 原因=%d", MAC2STR(event->mac), event->aid, event->reason);}
}/* 初始化WiFi AP */
void wifi_init_softap(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 = EXAMPLE_ESP_WIFI_SSID,.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.password = EXAMPLE_ESP_WIFI_PASS,.max_connection = EXAMPLE_MAX_STA_CONN,.authmode = WIFI_AUTH_WPA2_PSK,.pmf_cfg = {.required = true,},},};if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0){wifi_config.ap.authmode = WIFI_AUTH_OPEN;}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, "WiFi AP啟動完成. SSID:%s 密碼:%s 信道:%d",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}/* HTTP請求處理函數:處理根路徑"/"的GET請求,返回帶實時數據的HTML頁面 */
static esp_err_t root_get_handler(httpd_req_t *req)
{// 分配內存存儲HTML內容(長度為模板長度+200,預留數據填充空間)char *html_content = (char *)malloc(strlen(HTML_PAGE) + 200);if (!html_content){ // 若內存分配失敗httpd_resp_send_500(req); // 發送500(服務器內部錯誤)響應return ESP_FAIL; // 返回失敗}// 格式化HTML內容,將實時數據填充到HTML代碼模板的占位符中snprintf(html_content, strlen(HTML_PAGE) + 200, HTML_PAGE,Tem / 10.0f, // 溫度(實際值 = 存儲值/10)Hum / 10.0f, // 濕度(實際值 = 存儲值/10)Voltage, // 電壓Current / 10.0f, // 電流(實際值 = 存儲值/10)Power); // 功率// 發送HTTP響應httpd_resp_set_type(req, "text/html");httpd_resp_send(req, html_content, strlen(html_content));free(html_content); // 釋放內存return ESP_OK;
}/* HTTP服務器URI配置:定義根路徑"/"的處理規則 */
static httpd_uri_t root = {.uri = "/", // 匹配的URI路徑.method = HTTP_GET, // 支持的HTTP方法(GET).handler = root_get_handler, // GET方法的 處理函數.user_ctx = NULL // 用戶上下文數據(無)
};/* 啟動HTTP服務器 */
static httpd_handle_t start_webserver(void)
{httpd_handle_t server = NULL; // 服務器句柄httpd_config_t config = HTTPD_DEFAULT_CONFIG(); // 默認服務器配置config.lru_purge_enable = true; // 啟用LRU(最近最少使用)緩存清理// 啟動HTTP服務器if (httpd_start(&server, &config) == ESP_OK){// 注冊根路徑"/"的處理函數httpd_register_uri_handler(server, &root);ESP_LOGI(TAG, "HTTP服務器已啟動,端口: %d", config.server_port);return server;}ESP_LOGE(TAG, "HTTP服務器啟動失敗!");return NULL;
}void app_main(void)
{// 初始化NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND){ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);// 初始化UARTuart_config_t uart_config = {.baud_rate = 9600,.data_bits = UART_DATA_8_BITS,.parity = UART_PARITY_DISABLE,.stop_bits = UART_STOP_BITS_1,.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,.source_clk = UART_SCLK_DEFAULT,};uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);uart_param_config(EX_UART_NUM, &uart_config);uart_set_pin(EX_UART_NUM, GPIO_NUM_4, GPIO_NUM_5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);// 創建任務xTaskCreate(uart_event_task, "uart_event_task", 4046, NULL, 12, NULL);xTaskCreate(uart_T_task, "uart_T_task", 4046, NULL, 10, NULL);// 初始化時間setenv("TZ", "CST-8", 1);tzset(); // 應用時區設置// 初始化WiFi和HTTP服務器ESP_LOGI(TAG, "初始化WiFi AP...");wifi_init_softap();ESP_LOGI(TAG, "啟動HTTP服務器...");httpd_handle_t server = start_webserver();ESP_LOGI(TAG, "系統已啟動完成");ESP_LOGI(TAG, "請連接熱點: %s", EXAMPLE_ESP_WIFI_SSID);ESP_LOGI(TAG, "然后在瀏覽器訪問: http://192.168.4.1");
}