ESP-idf框架下的HTTP服務器\HTML 485溫濕度采集并長傳

項目描述:

本項目采用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");
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94442.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

雅江工程解鎖墨脫秘境:基礎條件全展示(區位、地震、景點、天氣)

目錄 前言 一、區位信息 1、空間位置 2、區位介紹 二、地震信息 1、歷史地震信息 2、5.0級以上大地震 三、景點信息 1、景點列表分布 2、4A級以上景點 四、天氣信息 1、天氣實況 2、天氣應對挑戰 五、總結 前言 相信最近大家對雅江電站的超級大工程項目應該有所耳…

??機器學習貝葉斯算法

??一、引言??在當今機器學習領域&#xff0c;貝葉斯算法猶如一顆璀璨的明星。你是否想過&#xff0c;垃圾郵件過濾系統是如何準確判斷一封郵件是否為垃圾郵件的呢&#xff1f;這背后可能就有貝葉斯算法的功勞。今天&#xff0c;我們就一同走進貝葉斯算法的世界&#xff0c;…

Chisel芯片開發入門系列 -- 18. CPU芯片開發和解釋8(流水線架構的代碼級理解)

以【5 Stage pipeline CPU】搜索圖片&#xff0c;選取5幅有代表性的圖列舉如下&#xff0c;并結合Chisel代碼進行理解和點評。 圖1&#xff1a;原文鏈接如下 https://acsweb.ucsd.edu/~dol031/posts/update/2023/04/10/5stage-cpu-pipeline.html 點評&#xff1a;黑色的部分…

Docker容器中文PDF生成解決方案

在Docker容器中生成包含中文內容的PDF文件時&#xff0c;經常遇到中文字符顯示為方塊或亂碼的問題。本文將詳細介紹如何在Docker環境中配置中文字體支持&#xff0c;實現完美的中文PDF生成。 問題現象 當使用wkhtmltopdf、Puppeteer或其他PDF生成工具時&#xff1a; 中文字符…

2.java集合,線程面試題(已實踐,目前已找到工作)

1線程的創建方式 繼承Thread類實現Runnable接口實現Callable接口 2.這三種方式在項目中的使用有哪些&#xff0c;一般都是怎么用的 繼承thread類實現線程的方式通過實現run方法來實現線程&#xff0c;通過run進行線程的啟用實現runnable方法實現run方法&#xff0c;然后通過thr…

站在前端的角度,看鴻蒙頁面布局

從Web前端轉向鴻蒙&#xff08;HarmonyOS&#xff09;開發時&#xff0c;理解其頁面布局的相似與差異是快速上手的核心。鴻蒙的ArkUI框架在布局理念上與Web前端有諸多相通之處&#xff0c;但也存在關鍵區別。以下從五個維度系統分析&#xff1a; &#x1f4e6; 一、盒子模型&a…

JavaWeb遺傳算法、TSP、模擬退火、ACO算法等實戰應用

Java Web中實現遺傳算法的應用 以下是關于Java Web中實現遺傳算法的應用場景和實例的整理,涵蓋不同領域的解決方案和實現方法: 遺傳算法基礎結構 在Java Web中實現遺傳算法通常需要以下核心組件: 種群初始化:隨機生成初始解集。 適應度函數:評估個體優劣。 選擇操作:輪…

【圖像算法 - 09】基于深度學習的煙霧檢測:從算法原理到工程實現,完整實戰指南

一、項目背景與需求 視頻介紹 【圖像算法 - 09】基于深度學習的煙霧檢測&#xff1a;從算法原理到工程實現&#xff0c;完整實戰指南今天我們使用深度學習來訓練一個煙霧明火檢測系統。這次我們使用了大概一萬五千張圖片的數據集訓練了這次的基于深度學習的煙霧明火檢測模型&a…

間接制冷技術概念及特征

1、基本概念 (1)間接制冷技術即二次制冷技術。常規做法:二次冷卻液儲液罐增加放置于制冷系統管路,促使冷量再快捷的傳遞給載冷劑,繼而載冷劑冷量促使冷庫達到制冷效果。間接制冷技術:通過常壓的二次冷卻介質進行大循環傳送冷量,在直接制冷劑不易應用的位置或者不可運用直…

Antlr學習筆記 01、maven配置Antlr4插件案例Demo

文章目錄前言源碼插件描述pom引入插件案例&#xff1a;實現hello 標識符 案例1、引入Antlr4的pom運行依賴2、定義語義語法&#xff0c;配置.g4文件實現java代碼3、編寫完之后&#xff0c;執行命令實現編譯4、編寫單測測試使用參考文章資料獲取前言 博主介紹&#xff1a;?目前…

PostGIS面試題及詳細答案120道之 (101-110 )

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

第十七天:原碼、反碼、補碼與位運算

原碼、反碼、補碼與位運算 一、原碼、反碼、補碼 1、原碼 定義&#xff1a;原碼是一種簡單的機器數表示法。對于一個有符號整數&#xff0c;最高位為符號位&#xff0c; 0 表示正數&#xff0c; 1 表示負數&#xff0c;其余位表示數值的絕對值。示例&#xff1a;以 8 位二進制…

一次完整的 Docker 啟動失敗排錯之旅:從 `start-limit` 到 `network not found

一次完整的 Docker 啟動失敗排錯之旅&#xff1a;從 start-limit 到 network not found 你是否也曾自信地敲下 sudo systemctl start docker&#xff0c;卻只得到一個冰冷的 failed&#xff1f;這是一個開發者和運維工程師都可能遇到的場景。本文將通過一個真實的排錯案例&…

Tdengine 時序庫年月日小時分組匯總問題

年月分組select to_char(collection_time ,"yyyy-mm") AS date, cast(SUM(a.stage_value)as DOUBLE) as stage_value from TABLE GROUP BY date年月日分組select to_char(collection_time ,"yyyy-mm-dd") AS date, SUM(a.stage_value)as DOUBLE) as stage_…

數據結構(01)—— 數據結構的基本概念

408前置學習C語言基礎也可以看如下專欄&#xff1a;打怪升級之路——C語言之路_ankleless的博客-CSDN博客 目錄 1. 基本概念 1.1 數據 1.2 數據元素 1.3 數據項 1.4 組合項 1.5 數據對象 1.6 數據類型 2. 數據結構 2.1 邏輯結構 2.2 存儲結構 2.3 數據的運算 在學…

什么是模型并行?

模型并行c 簡單來說&#xff0c;就是把一個模型拆開來放到多個 GPU 上&#xff0c;一起訓練&#xff0c;從而化解“顯存塞不下模型”的問題!更多專業課程內容可以聽取工信部電子標準院《人工智能大模型應用工程師》課程獲得詳解&#xff01;

跑yolov5的train.py時,ImportError: Failed to initialize: Bad git executable.

遇到的問題&#xff1a; Traceback (most recent call last):File "D:\miniconda\envs\yolov5\lib\site-packages\git\__init__.py", line 296, in <module>refresh()File "D:\miniconda\envs\yolov5\lib\site-packages\git\__init__.py", line 287…

TCP如何實現可靠傳輸?實現細節?

TCP如何實現可靠傳輸&#xff1f;實現細節&#xff1f;如何實現可靠傳輸&#xff1f;擁塞控制的主要機制TCP流量控制怎么實現的&#xff1f;如何實現可靠傳輸&#xff1f; TCP通過自身的序列號、確認應答、數據效驗、超時重傳、流量控制、擁塞避免&#xff0c;確保了數據傳輸的…

Linux 服務器性能監控、分析與優化全指南

Linux 服務器性能監控、分析與優化在現代 IT 架構中&#xff0c;Linux 服務器作為承載業務系統的核心載體&#xff0c;其性能表現直接決定了服務的穩定性、響應速度與用戶體驗。無論是高并發的 Web 服務、數據密集型的數據庫集群&#xff0c;還是承載虛擬化平臺的宿主機&#x…

基于wenet和模型做企業直播敏感語音屏蔽技術

本文介紹了基于Wenet語音識別工具包的實時敏感詞屏蔽技術方案。該方案通過客戶端緩存25秒直播內容&#xff0c;利用Wenet的流式識別和斷句檢測功能&#xff0c;實時檢測講師語音中的敏感詞&#xff0c;并將對應位置的語音替換為"嗶"聲。文章詳細闡述了Wenet的兩種識別…