Files
bishe-STM32/Hardware/esp8266_new.c
T
2026-05-01 20:29:02 +08:00

244 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
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.
/*
* ESP8266 WiFi模块驱动(支持HTTP加密传输)
* 新增功能:
* 1. HTTP POST请求支持
* 2. 加密数据传输
* 3. 自动重连机制
*/
#include "esp8266.h"
#include "Serial.h"
#include "Delay.h"
#include <stdio.h>
#include <string.h>
// 外部配置(在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;
}