11.esp8266面向对象的封装
约 2214 字大约 7 分钟
2025-08-20
/* ============================================================================
* ESP8266面向对象封装 - 头文件
* 文件: esp8266_oop.h
* ============================================================================ */
#ifndef __ESP8266_OOP_H__
#define __ESP8266_OOP_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
/* 常量定义 */
#define ESP8266_SSID_MAX_LEN 32
#define ESP8266_PASSWORD_MAX_LEN 64
#define ESP8266_IP_STR_LEN 16
#define ESP8266_MAC_STR_LEN 18
#define ESP8266_BUFFER_SIZE 256
/* 枚举定义 */
typedef enum {
ESP8266_OK = 0,
ESP8266_ERROR,
ESP8266_TIMEOUT,
ESP8266_INVALID_PARAM,
ESP8266_NOT_INITIALIZED,
ESP8266_WIFI_NOT_CONNECTED,
ESP8266_MEMORY_ERROR
} ESP8266_Result_t;
typedef enum {
ESP8266_MODE_STA = 1,
ESP8266_MODE_AP = 2,
ESP8266_MODE_STA_AP = 3
} ESP8266_Mode_t;
typedef enum {
ESP8266_WIFI_DISCONNECTED = 0,
ESP8266_WIFI_CONNECTED = 1,
ESP8266_WIFI_CONNECTING = 2,
ESP8266_WIFI_ERROR = 3
} ESP8266_WiFi_Status_t;
typedef enum {
ESP8266_ENCRYPT_OPEN = 0,
ESP8266_ENCRYPT_WEP,
ESP8266_ENCRYPT_WPA_PSK,
ESP8266_ENCRYPT_WPA2_PSK,
ESP8266_ENCRYPT_WPA_WPA2_PSK
} ESP8266_Encrypt_t;
/* 前向声明 */
typedef struct ESP8266_Class ESP8266_t;
/* WiFi信息结构体 */
typedef struct {
char ssid[ESP8266_SSID_MAX_LEN];
char password[ESP8266_PASSWORD_MAX_LEN];
ESP8266_Encrypt_t encryption;
int8_t rssi;
} ESP8266_WiFi_Info_t;
/* 网络信息结构体 */
typedef struct {
char ip[ESP8266_IP_STR_LEN];
char gateway[ESP8266_IP_STR_LEN];
char netmask[ESP8266_IP_STR_LEN];
char mac[ESP8266_MAC_STR_LEN];
} ESP8266_Network_Info_t;
/* 虚函数表(接口定义) */
typedef struct {
/* 基础操作 - 纯虚函数 */
ESP8266_Result_t (*init)(ESP8266_t *this);
ESP8266_Result_t (*deinit)(ESP8266_t *this);
ESP8266_Result_t (*reset)(ESP8266_t *this);
ESP8266_Result_t (*send_cmd)(ESP8266_t *this, const char *cmd, char *response, uint32_t timeout);
/* WiFi操作 */
ESP8266_Result_t (*set_mode)(ESP8266_t *this, ESP8266_Mode_t mode);
ESP8266_Mode_t (*get_mode)(ESP8266_t *this);
ESP8266_Result_t (*connect_wifi)(ESP8266_t *this, const char *ssid, const char *password);
ESP8266_Result_t (*disconnect_wifi)(ESP8266_t *this);
ESP8266_WiFi_Status_t (*get_wifi_status)(ESP8266_t *this);
ESP8266_Result_t (*scan_wifi)(ESP8266_t *this, ESP8266_WiFi_Info_t *wifi_list, uint8_t *count);
/* 网络操作 */
ESP8266_Result_t (*get_network_info)(ESP8266_t *this, ESP8266_Network_Info_t *info);
ESP8266_Result_t (*create_tcp_server)(ESP8266_t *this, uint16_t port);
ESP8266_Result_t (*create_tcp_client)(ESP8266_t *this, const char *host, uint16_t port);
ESP8266_Result_t (*send_data)(ESP8266_t *this, const uint8_t *data, uint16_t len);
ESP8266_Result_t (*receive_data)(ESP8266_t *this, uint8_t *data, uint16_t *len, uint32_t timeout);
/* HTTP操作 */
ESP8266_Result_t (*http_get)(ESP8266_t *this, const char *url, char *response, uint16_t *len);
ESP8266_Result_t (*http_post)(ESP8266_t *this, const char *url, const char *data, char *response, uint16_t *len);
} ESP8266_VTable_t;
/* ESP8266基类 */
struct ESP8266_Class {
/* 虚函数表指针 */
const ESP8266_VTable_t *vtable;
/* 私有数据成员 */
ESP8266_Mode_t mode;
ESP8266_WiFi_Status_t wifi_status;
ESP8266_WiFi_Info_t current_wifi;
ESP8266_Network_Info_t network_info;
/* 状态标志 */
bool initialized;
bool connected;
/* 缓冲区 */
char cmd_buffer[ESP8266_BUFFER_SIZE];
char response_buffer[ESP8266_BUFFER_SIZE];
/* 硬件抽象层接口(需要子类实现) */
void (*hw_send_byte)(uint8_t data);
uint8_t (*hw_receive_byte)(void);
bool (*hw_data_available)(void);
void (*hw_delay_ms)(uint32_t ms);
uint32_t (*hw_get_tick)(void);
};
/* ============================================================================
* 公共接口函数 - 面向对象方法调用
* ============================================================================ */
/* 构造函数 */
ESP8266_Result_t ESP8266_Construct(ESP8266_t *this, const ESP8266_VTable_t *vtable);
/* 析构函数 */
void ESP8266_Destruct(ESP8266_t *this);
/* 基础操作方法 */
static inline ESP8266_Result_t ESP8266_Init(ESP8266_t *this) {
return this->vtable->init(this);
}
static inline ESP8266_Result_t ESP8266_Deinit(ESP8266_t *this) {
return this->vtable->deinit(this);
}
static inline ESP8266_Result_t ESP8266_Reset(ESP8266_t *this) {
return this->vtable->reset(this);
}
/* WiFi操作方法 */
static inline ESP8266_Result_t ESP8266_SetMode(ESP8266_t *this, ESP8266_Mode_t mode) {
return this->vtable->set_mode(this, mode);
}
static inline ESP8266_Mode_t ESP8266_GetMode(ESP8266_t *this) {
return this->vtable->get_mode(this);
}
static inline ESP8266_Result_t ESP8266_ConnectWiFi(ESP8266_t *this, const char *ssid, const char *password) {
return this->vtable->connect_wifi(this, ssid, password);
}
static inline ESP8266_Result_t ESP8266_DisconnectWiFi(ESP8266_t *this) {
return this->vtable->disconnect_wifi(this);
}
static inline ESP8266_WiFi_Status_t ESP8266_GetWiFiStatus(ESP8266_t *this) {
return this->vtable->get_wifi_status(this);
}
/* 网络操作方法 */
static inline ESP8266_Result_t ESP8266_GetNetworkInfo(ESP8266_t *this, ESP8266_Network_Info_t *info) {
return this->vtable->get_network_info(this, info);
}
static inline ESP8266_Result_t ESP8266_CreateTCPServer(ESP8266_t *this, uint16_t port) {
return this->vtable->create_tcp_server(this, port);
}
static inline ESP8266_Result_t ESP8266_CreateTCPClient(ESP8266_t *this, const char *host, uint16_t port) {
return this->vtable->create_tcp_client(this, host, port);
}
static inline ESP8266_Result_t ESP8266_SendData(ESP8266_t *this, const uint8_t *data, uint16_t len) {
return this->vtable->send_data(this, data, len);
}
static inline ESP8266_Result_t ESP8266_ReceiveData(ESP8266_t *this, uint8_t *data, uint16_t *len, uint32_t timeout) {
return this->vtable->receive_data(this, data, len, timeout);
}
/* HTTP操作方法 */
static inline ESP8266_Result_t ESP8266_HttpGet(ESP8266_t *this, const char *url, char *response, uint16_t *len) {
return this->vtable->http_get(this, url, response, len);
}
static inline ESP8266_Result_t ESP8266_HttpPost(ESP8266_t *this, const char *url, const char *data, char *response, uint16_t *len) {
return this->vtable->http_post(this, url, data, response, len);
}
/* ============================================================================
* 辅助函数
* ============================================================================ */
const char* ESP8266_GetResultString(ESP8266_Result_t result);
const char* ESP8266_GetModeString(ESP8266_Mode_t mode);
const char* ESP8266_GetWiFiStatusString(ESP8266_WiFi_Status_t status);
#endif /* __ESP8266_OOP_H__ */
/* ============================================================================
* ESP8266面向对象封装 - 实现文件
* 文件: esp8266_oop.c
* ============================================================================ */
#include "esp8266_oop.h"
#include <stdio.h>
#include <stdlib.h>
/* ============================================================================
* 基类实现
* ============================================================================ */
/* 构造函数实现 */
ESP8266_Result_t ESP8266_Construct(ESP8266_t *this, const ESP8266_VTable_t *vtable) {
if (this == NULL || vtable == NULL) {
return ESP8266_INVALID_PARAM;
}
/* 初始化虚函数表 */
this->vtable = vtable;
/* 初始化成员变量 */
this->mode = ESP8266_MODE_STA;
this->wifi_status = ESP8266_WIFI_DISCONNECTED;
this->initialized = false;
this->connected = false;
/* 清空结构体 */
memset(&this->current_wifi, 0, sizeof(ESP8266_WiFi_Info_t));
memset(&this->network_info, 0, sizeof(ESP8266_Network_Info_t));
memset(this->cmd_buffer, 0, ESP8266_BUFFER_SIZE);
memset(this->response_buffer, 0, ESP8266_BUFFER_SIZE);
/* 硬件接口指针初始化为NULL(需要子类设置) */
this->hw_send_byte = NULL;
this->hw_receive_byte = NULL;
this->hw_data_available = NULL;
this->hw_delay_ms = NULL;
this->hw_get_tick = NULL;
return ESP8266_OK;
}
/* 析构函数实现 */
void ESP8266_Destruct(ESP8266_t *this) {
if (this != NULL && this->initialized) {
/* 调用析构函数 */
if (this->vtable && this->vtable->deinit) {
this->vtable->deinit(this);
}
/* 清理资源 */
this->initialized = false;
this->connected = false;
this->vtable = NULL;
}
}
/* ============================================================================
* 辅助函数实现
* ============================================================================ */
const char* ESP8266_GetResultString(ESP8266_Result_t result) {
switch (result) {
case ESP8266_OK: return "OK";
case ESP8266_ERROR: return "ERROR";
case ESP8266_TIMEOUT: return "TIMEOUT";
case ESP8266_INVALID_PARAM: return "INVALID_PARAM";
case ESP8266_NOT_INITIALIZED: return "NOT_INITIALIZED";
case ESP8266_WIFI_NOT_CONNECTED: return "WIFI_NOT_CONNECTED";
case ESP8266_MEMORY_ERROR: return "MEMORY_ERROR";
default: return "UNKNOWN";
}
}
const char* ESP8266_GetModeString(ESP8266_Mode_t mode) {
switch (mode) {
case ESP8266_MODE_STA: return "STA";
case ESP8266_MODE_AP: return "AP";
case ESP8266_MODE_STA_AP: return "STA+AP";
default: return "UNKNOWN";
}
}
const char* ESP8266_GetWiFiStatusString(ESP8266_WiFi_Status_t status) {
switch (status) {
case ESP8266_WIFI_DISCONNECTED: return "DISCONNECTED";
case ESP8266_WIFI_CONNECTED: return "CONNECTED";
case ESP8266_WIFI_CONNECTING: return "CONNECTING";
case ESP8266_WIFI_ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
/* ============================================================================
* 具体实现类示例 - ESP8266 AT命令实现
* 文件: esp8266_at.c
* ============================================================================ */
/* AT命令实现的虚函数表 */
static ESP8266_Result_t ESP8266_AT_Init(ESP8266_t *this);
static ESP8266_Result_t ESP8266_AT_Deinit(ESP8266_t *this);
static ESP8266_Result_t ESP8266_AT_Reset(ESP8266_t *this);
static ESP8266_Result_t ESP8266_AT_SendCmd(ESP8266_t *this, const char *cmd, char *response, uint32_t timeout);
static ESP8266_Result_t ESP8266_AT_SetMode(ESP8266_t *this, ESP8266_Mode_t mode);
static ESP8266_Mode_t ESP8266_AT_GetMode(ESP8266_t *this);
static ESP8266_Result_t ESP8266_AT_ConnectWiFi(ESP8266_t *this, const char *ssid, const char *password);
static ESP8266_Result_t ESP8266_AT_DisconnectWiFi(ESP8266_t *this);
static ESP8266_WiFi_Status_t ESP8266_AT_GetWiFiStatus(ESP8266_t *this);
static ESP8266_Result_t ESP8266_AT_GetNetworkInfo(ESP8266_t *this, ESP8266_Network_Info_t *info);
/* AT命令实现的虚函数表定义 */
const ESP8266_VTable_t ESP8266_AT_VTable = {
.init = ESP8266_AT_Init,
.deinit = ESP8266_AT_Deinit,
.reset = ESP8266_AT_Reset,
.send_cmd = ESP8266_AT_SendCmd,
.set_mode = ESP8266_AT_SetMode,
.get_mode = ESP8266_AT_GetMode,
.connect_wifi = ESP8266_AT_ConnectWiFi,
.disconnect_wifi = ESP8266_AT_DisconnectWiFi,
.get_wifi_status = ESP8266_AT_GetWiFiStatus,
.get_network_info = ESP8266_AT_GetNetworkInfo,
/* 其他函数可以设置为NULL或实现 */
.scan_wifi = NULL,
.create_tcp_server = NULL,
.create_tcp_client = NULL,
.send_data = NULL,
.receive_data = NULL,
.http_get = NULL,
.http_post = NULL
};
/* AT命令实现的具体函数 */
static ESP8266_Result_t ESP8266_AT_Init(ESP8266_t *this) {
if (this == NULL) return ESP8266_INVALID_PARAM;
/* 检查硬件接口是否已设置 */
if (!this->hw_send_byte || !this->hw_receive_byte ||
!this->hw_data_available || !this->hw_delay_ms) {
return ESP8266_NOT_INITIALIZED;
}
/* 发送AT测试命令 */
ESP8266_Result_t result = ESP8266_AT_SendCmd(this, "AT", this->response_buffer, 1000);
if (result == ESP8266_OK) {
this->initialized = true;
}
return result;
}
static ESP8266_Result_t ESP8266_AT_SendCmd(ESP8266_t *this, const char *cmd, char *response, uint32_t timeout) {
if (!this || !cmd) return ESP8266_INVALID_PARAM;
/* 发送命令 */
const char *p = cmd;
while (*p) {
this->hw_send_byte(*p++);
}
this->hw_send_byte('\r');
this->hw_send_byte('\n');
/* 接收响应 */
uint32_t start_time = this->hw_get_tick();
uint16_t idx = 0;
while ((this->hw_get_tick() - start_time) < timeout) {
if (this->hw_data_available()) {
uint8_t data = this->hw_receive_byte();
if (response && idx < ESP8266_BUFFER_SIZE - 1) {
response[idx++] = data;
}
/* 检查是否收到OK或ERROR */
if (strstr(response, "OK")) {
response[idx] = '\0';
return ESP8266_OK;
}
if (strstr(response, "ERROR")) {
response[idx] = '\0';
return ESP8266_ERROR;
}
}
this->hw_delay_ms(1);
}
return ESP8266_TIMEOUT;
}
static ESP8266_Result_t ESP8266_AT_ConnectWiFi(ESP8266_t *this, const char *ssid, const char *password) {
if (!this || !ssid || !password) return ESP8266_INVALID_PARAM;
if (!this->initialized) return ESP8266_NOT_INITIALIZED;
/* 设置为STA模式 */
ESP8266_Result_t result = ESP8266_AT_SetMode(this, ESP8266_MODE_STA);
if (result != ESP8266_OK) return result;
/* 构建连接命令 */
snprintf(this->cmd_buffer, ESP8266_BUFFER_SIZE,
"AT+CWJAP=\"%s\",\"%s\"", ssid, password);
/* 发送连接命令 */
result = ESP8266_AT_SendCmd(this, this->cmd_buffer, this->response_buffer, 10000);
if (result == ESP8266_OK) {
/* 保存WiFi信息 */
strncpy(this->current_wifi.ssid, ssid, ESP8266_SSID_MAX_LEN - 1);
strncpy(this->current_wifi.password, password, ESP8266_PASSWORD_MAX_LEN - 1);
this->wifi_status = ESP8266_WIFI_CONNECTED;
this->connected = true;
}
return result;
}
/* 其他AT命令实现函数... */
static ESP8266_Result_t ESP8266_AT_Deinit(ESP8266_t *this) {
if (this) this->initialized = false;
return ESP8266_OK;
}
static ESP8266_Result_t ESP8266_AT_Reset(ESP8266_t *this) {
return ESP8266_AT_SendCmd(this, "AT+RST", this->response_buffer, 2000);
}
static ESP8266_Result_t ESP8266_AT_SetMode(ESP8266_t *this, ESP8266_Mode_t mode) {
snprintf(this->cmd_buffer, ESP8266_BUFFER_SIZE, "AT+CWMODE=%d", mode);
ESP8266_Result_t result = ESP8266_AT_SendCmd(this, this->cmd_buffer, this->response_buffer, 1000);
if (result == ESP8266_OK) {
this->mode = mode;
}
return result;
}
static ESP8266_Mode_t ESP8266_AT_GetMode(ESP8266_t *this) {
return this->mode;
}
static ESP8266_Result_t ESP8266_AT_DisconnectWiFi(ESP8266_t *this) {
ESP8266_Result_t result = ESP8266_AT_SendCmd(this, "AT+CWQAP", this->response_buffer, 1000);
if (result == ESP8266_OK) {
this->wifi_status = ESP8266_WIFI_DISCONNECTED;
this->connected = false;
}
return result;
}
static ESP8266_WiFi_Status_t ESP8266_AT_GetWiFiStatus(ESP8266_t *this) {
return this->wifi_status;
}
static ESP8266_Result_t ESP8266_AT_GetNetworkInfo(ESP8266_t *this, ESP8266_Network_Info_t *info) {
/* 获取IP信息的实现 */
ESP8266_Result_t result = ESP8266_AT_SendCmd(this, "AT+CIFSR", this->response_buffer, 1000);
if (result == ESP8266_OK && info) {
/* 解析响应并填充网络信息 */
/* 这里需要解析AT+CIFSR的响应格式 */
strcpy(info->ip, "192.168.1.100"); // 示例
strcpy(info->gateway, "192.168.1.1");
strcpy(info->netmask, "255.255.255.0");
strcpy(info->mac, "AA:BB:CC:DD:EE:FF");
}
return result;
}
/* ============================================================================
* 使用示例
* ============================================================================ */
/* 硬件抽象层实现示例(需要根据具体硬件平台实现) */
void hw_uart_send_byte(uint8_t data) {
/* 发送一个字节到UART */
// 具体实现依赖于硬件平台
}
uint8_t hw_uart_receive_byte(void) {
/* 从UART接收一个字节 */
// 具体实现依赖于硬件平台
return 0;
}
bool hw_uart_data_available(void) {
/* 检查UART是否有数据可读 */
// 具体实现依赖于硬件平台
return false;
}
void hw_delay_ms(uint32_t ms) {
/* 毫秒级延时 */
// 具体实现依赖于硬件平台
}
uint32_t hw_get_tick_ms(void) {
/* 获取系统时钟(毫秒) */
// 具体实现依赖于硬件平台
return 0;
}
/* 使用示例 */
void example_usage(void) {
ESP8266_t wifi_module;
ESP8266_Result_t result;
ESP8266_Network_Info_t net_info;
/* 1. 构造对象 */
result = ESP8266_Construct(&wifi_module, &ESP8266_AT_VTable);
if (result != ESP8266_OK) {
printf("构造失败: %s\n", ESP8266_GetResultString(result));
return;
}
/* 2. 设置硬件抽象层接口 */
wifi_module.hw_send_byte = hw_uart_send_byte;
wifi_module.hw_receive_byte = hw_uart_receive_byte;
wifi_module.hw_data_available = hw_uart_data_available;
wifi_module.hw_delay_ms = hw_delay_ms;
wifi_module.hw_get_tick = hw_get_tick_ms;
/* 3. 初始化模块 */
result = ESP8266_Init(&wifi_module);
if (result != ESP8266_OK) {
printf("初始化失败: %s\n", ESP8266_GetResultString(result));
ESP8266_Destruct(&wifi_module);
return;
}
/* 4. 连接WiFi */
result = ESP8266_ConnectWiFi(&wifi_module, "MyWiFi", "password123");
if (result == ESP8266_OK) {
printf("WiFi连接成功\n");
/* 5. 获取网络信息 */
result = ESP8266_GetNetworkInfo(&wifi_module, &net_info);
if (result == ESP8266_OK) {
printf("IP: %s\n", net_info.ip);
printf("Gateway: %s\n", net_info.gateway);
printf("MAC: %s\n", net_info.mac);
}
} else {
printf("WiFi连接失败: %s\n", ESP8266_GetResultString(result));
}
/* 6. 清理资源 */
ESP8266_Destruct(&wifi_module);
}
/*
面向对象设计特性说明:
1. 封装 (Encapsulation):
- 数据成员私有化,通过公共接口访问
- 隐藏内部实现细节
- 提供清晰的API接口
2. 继承 (Inheritance):
- 基类定义通用接口和数据结构
- 派生类实现具体功能(如AT命令实现)
- 可以轻松扩展新的实现(如SPI实现)
3. 多态 (Polymorphism):
- 通过虚函数表实现运行时多态
- 相同接口可以有不同实现
- 支持动态绑定
4. 抽象 (Abstraction):
- 定义抽象接口(虚函数表)
- 隐藏具体实现细节
- 提供统一的使用方式
5. 组合 (Composition):
- 硬件抽象层通过函数指针组合
- 灵活适配不同硬件平台
- 降低耦合度
优势:
- 代码复用性高
- 易于维护和扩展
- 良好的模块化设计
- 支持不同的硬件平台
- 类型安全
*/