共计 1686 个字符,预计需要花费 5 分钟才能阅读完成。
开篇:ESP32 接入 AI 服务的三大挑战
最近在折腾 ESP32 接入 ChatGPT 时,发现三个让人头疼的问题:

- API 调用成本 :官方 API 按 token 计费,做个 demo 都能刷爆信用卡
- 网络延迟 :WiFi 信号不稳时,一次对话可能要等 10 秒以上
- 内存限制 :ESP32 的 520KB RAM 连大点的 JSON 都装不下
技术方案选型
方案对比
- 官方 API:稳定但烧钱,适合不差钱的企业项目
- text-generation-webui:本地部署的 LLM 方案,需要额外服务器但零 API 成本
经过实测,推荐组合方案:用开源模型处理简单指令,复杂问题再走 API。比如天气查询这类固定问答完全可以在本地处理。
HTTP 长连接复用
关键代码片段(PlatformIO 环境验证通过):
// 创建持久化连接
HTTPClient http;
http.setReuse(true); // 重点!减少 TCP 握手次数
http.begin("https://api.openai.com/v1/chat/completions");
http.addHeader("Content-Type", "application/json");
// 发送请求时指定 Keep-Alive
const char* postData = "{\"model\":\"gpt-3.5-turbo\"...}";
int httpCode = http.POST(postData);
性能优化实战
PROGMEM 妙用
把固定 prompt 存到 Flash 省 RAM:
const char systemPrompt[] PROGMEM = "你是一个物联网设备助手...";
void setup() {char buffer[200];
memcpy_P(buffer, systemPrompt, sizeof(systemPrompt));
// 现在 buffer 里就有完整 prompt 了
}
FreeRTOS 任务配置
在 platformio.ini 中添加:
[env:esp32dev]
platform = espressif32
framework = arduino
board = esp32dev
monitor_speed = 115200
board_build.f_cpu = 240000000L
然后设置网络任务为高优先级:
xTaskCreatePinnedToCore(
networkTask, // 任务函数
"NetTask", // 任务名
8192, // 堆栈大小
NULL, // 参数
3, // 优先级 (数字越大越高)
NULL, // 任务句柄
1 // 核心编号
);
安全防护措施
API 密钥存储
使用 ESP32 的 NVS 加密存储:
#include <nvs.h>
#include <nvs_flash.h>
nvs_handle_t handle;
nvs_open("storage", NVS_READWRITE, &handle);
// 写入密钥
nvs_set_str(handle, "api_key", "sk-xxxxxx");
// 读取时
char api_key[64];
size_t len = sizeof(api_key);
nvs_get_str(handle, "api_key", api_key, &len);
输入过滤
简单的注入防御:
String sanitizeInput(String input) {input.replace("\\", "\\\\"); // 转义反斜杠
input.replace("\"", "\\\""); // 转义双引号
input.replace("\n", " "); // 去除换行
return input.substring(0, 100); // 限制长度
}
生产环境检查清单
部署前必做事项:
- 启用硬件看门狗:
esp_task_wdt_init(30, true); - 配置 OTA 更新通道
- 设置内存监控任务
- 添加网络重连机制
- 禁用调试日志
思考延伸
最近在探索一个有趣的方向:用 Wake-on-Voice 技术实现离线唤醒后,再联网调用 ChatGPT。比如先说 ” 小 E 小 E ” 唤醒设备,再说 ” 打开客厅灯 ” 直接本地执行,说 ” 讲个笑话 ” 再走云端 API。你们觉得这个方案可行吗?欢迎在评论区讨论~
正文完
