/* * ESP8266 WiFi模块驱动(支持HTTP加密传输) * 新增功能: * 1. HTTP POST请求支持 * 2. 加密数据传输 * 3. 自动重连机制 */ #include "esp8266.h" #include "Serial.h" #include "Delay.h" #include #include // 外部配置(在main.c中定义) extern const char* WIFI_SSID; extern const char* WIFI_PASSWORD; extern const char* HTTP_SERVER_IP; extern const char* HTTP_SERVER_PORT; extern const char* HTTP_API_TOKEN; // 内部函数声明 static uint8_t ESP8266_SendCommand(const char* cmd, const char* expected, uint16_t timeout); static void ESP8266_ClearBuffer(void); /** * @brief 发送AT命令并等待响应 */ static uint8_t ESP8266_SendCommand(const char* cmd, const char* expected, uint16_t timeout) { Serial_SendString(cmd); Serial_SendString("\r\n"); Delay_ms(timeout); if (expected == NULL) { return ESP8266_SUCCESS; } // 检查是否收到期望的响应 char* response = Serial_GetRxData(); if (strstr(response, expected) != NULL) { return ESP8266_SUCCESS; } return ESP8266_FAIL; } static void ESP8266_ClearBuffer(void) { Serial_ClearRxBuffer(); } uint8_t ESP8266_Setup(void) { ESP8266_ClearBuffer(); // 测试AT指令 if (ESP8266_SendCommand("AT", "OK", 1000) == ESP8266_FAIL) { return ESP8266_FAIL; } // 设置为STA模式(客户端模式) if (ESP8266_SendCommand("AT+CWMODE=1", "OK", 1000) == ESP8266_FAIL) { return ESP8266_FAIL; } // 关闭回显 ESP8266_SendCommand("ATE0", "OK", 500); // 设置单连接模式 if (ESP8266_SendCommand("AT+CIPMUX=0", "OK", 1000) == ESP8266_FAIL) { return ESP8266_FAIL; } return ESP8266_SUCCESS; } uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password) { char cmd[128]; ESP8266_ClearBuffer(); // 断开之前的WiFi连接 ESP8266_SendCommand("AT+CWQAP", "OK", 1000); Delay_ms(1000); // 连接到WiFi sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, password); // WiFi连接可能需要较长时间 if (ESP8266_SendCommand(cmd, "OK", 10000) == ESP8266_FAIL) { return ESP8266_FAIL; } Delay_ms(2000); return ESP8266_SUCCESS; } uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port) { char cmd[64]; ESP8266_ClearBuffer(); // 断开之前的TCP连接 ESP8266_SendCommand("AT+CIPCLOSE", "OK", 1000); Delay_ms(500); // 建立TCP连接到HTTP服务器 sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s", ip, port); if (ESP8266_SendCommand(cmd, "OK", 5000) == ESP8266_FAIL) { return ESP8266_FAIL; } Delay_ms(1000); return ESP8266_SUCCESS; } uint8_t ESP8266_SendEncryptedData(const char* encrypted_data) { char http_request[1024]; char cmd[32]; uint32_t content_length = strlen(encrypted_data); // 构建HTTP POST请求 sprintf(http_request, "POST /api/v1/attendance/checkins HTTP/1.1\r\n" "Host: %s:%s\r\n" "Content-Type: application/octet-stream\r\n" "X-Api-Token: %s\r\n" "X-Encrypted: AES128-CBC\r\n" "Content-Length: %u\r\n" "Connection: keep-alive\r\n" "\r\n" "%s", HTTP_SERVER_IP, HTTP_SERVER_PORT, HTTP_API_TOKEN, content_length, encrypted_data ); uint32_t request_len = strlen(http_request); // 发送数据长度命令 sprintf(cmd, "AT+CIPSEND=%u", request_len); ESP8266_ClearBuffer(); if (ESP8266_SendCommand(cmd, ">", 2000) == ESP8266_FAIL) { return ESP8266_FAIL; } // 发送HTTP请求 Serial_SendString(http_request); // 等待发送完成(不阻塞太久) Delay_ms(100); // 可选:等待服务器响应(检查是否有"200 OK") // 但为了不阻塞,建议不等待 return ESP8266_SUCCESS; } uint8_t ESP8266_CheckConnection(void) { ESP8266_ClearBuffer(); if (ESP8266_SendCommand("AT+CIPSTATUS", "OK", 1000) == ESP8266_FAIL) { return ESP8266_FAIL; } // 检查响应中是否包含"STATUS:3"(已连接) char* response = Serial_GetRxData(); if (strstr(response, "STATUS:3") != NULL || strstr(response, "STATUS:4") != NULL) { return ESP8266_SUCCESS; } return ESP8266_FAIL; } uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime) { // 启用SNTP if (ESP8266_SendCommand("AT+CIPSNTPCFG=1,8,\"pool.ntp.org\"", "OK", 2000) == ESP8266_FAIL) { return ESP8266_FAIL; } Delay_ms(3000); // 等待时间同步 ESP8266_ClearBuffer(); // 获取时间 if (ESP8266_SendCommand("AT+CIPSNTPTIME?", "OK", 1000) == ESP8266_FAIL) { return ESP8266_FAIL; } // 解析响应(格式:+CIPSNTPTIME:Thu Jan 01 08:00:00 2024) char* response = Serial_GetRxData(); char* time_str = strstr(response, "+CIPSNTPTIME:"); if (time_str != NULL) { // 简单解析(这里只是示例,实际需要更完善的解析) sscanf(time_str, "+CIPSNTPTIME:%*s %*s %d %d:%d:%d %d", &datetime->day, &datetime->hour, &datetime->minute, &datetime->second, &datetime->year); return ESP8266_SUCCESS; } return ESP8266_FAIL; } // ========== 兼容旧版本的函数(已废弃) ========== uint8_t ESP8266_ConnectTCPServer(const char* ip, const char* port) { // 重定向到HTTP版本 return ESP8266_ConnectHTTPServer(ip, port); } uint8_t ESP8266_SendData(char* Data) { // 警告:此函数已废弃,请使用ESP8266_SendEncryptedData // 为了兼容,这里保留基本实现 char cmd[32]; sprintf(cmd, "AT+CIPSEND=%d", strlen(Data)); if (ESP8266_SendCommand(cmd, ">", 2000) == ESP8266_FAIL) { return ESP8266_FAIL; } Serial_SendString(Data); Delay_ms(50); return ESP8266_SUCCESS; }