实现ESP32woor连接deepseek进行访问
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h> //记得先安装库
// 配置信息
const char* ssid = "Xiaomi 15"; //wifi名字
const char* password = "12345678"; //wifi密码
const char* host = "api.deepseek.com"; //DeepSeek的网址
const int port = 443;
const char* apiKey = "............................."; //先注册,创建key。DeepSeek 密钥。注册送的10块,免费分享。
// 分块解析状态机
enum ChunkState { PARSE_CHUNK_SIZE, PARSE_CHUNK_DATA, PARSE_COMPLETE };
//类似main()函数
void setup() {
delay(1000);
Serial.begin(115200);
WiFi.setAutoReconnect(true);
connectToWiFi();
}
//类似while()循环
void loop() {
if (WiFi.status() != WL_CONNECTED) { //重新连接机制
Serial.println("\n[WARN] WiFi连接丢失,尝试重连...");
connectToWiFi();
delay(1000);
return;
}
if (Serial.available() > 0) { //获取串口字符串
String userInput = Serial.readStringUntil('\n');
userInput.trim();
if (userInput.length() > 0) {
Serial.printf("\n[ESP32] 发送消息:%s\r\n", userInput.c_str());
String response = sendDeepSeekRequest(userInput);
if (response.length() > 0) {
parseApiResponse(response);
}
}
Serial.println("\r\n[DeepSeek] 请输入问题给我(按回车发送):");
}
}
// WiFi连接函数
void connectToWiFi() {
WiFi.disconnect(); //先断开再连接,不然可能第一次连接超时
WiFi.mode(WIFI_STA); //STA模式
Serial.println("\n[ESP32] 正在连接WiFi...");
WiFi.begin(ssid, password);
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 30000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("\n[ESP32] 连接成功! IP地址: %s\n", WiFi.localIP().toString().c_str());
Serial.println("\r\n[DeepSeek] 请输入问题给我(按回车发送):");
} else {
Serial.println("\n[ERROR] 连接超时,请检查配置");
}
}
// API请求函数
String sendDeepSeekRequest(String userContent) {
WiFiClientSecure client; // 在这里正确声明客户端
client.setInsecure(); // 不验证证书
client.setTimeout(15000); // 设置整体超时时间
Serial.println("\r\n[ESP32] 正在连接API服务器...");
if (!client.connect(host, port)) {
Serial.println("[ERROR] API服务器连接失败");
return "";
}
// 构建JSON请求
StaticJsonDocument<512> requestDoc;
requestDoc["model"] = "deepseek-chat"; //deepseek-chat
requestDoc["max_tokens"] = 5000; // 限制响应长度,注意:这个是一次性返回多少个字,最好多一点,不然获取不完整!!!
JsonArray messages = requestDoc.createNestedArray("messages");
JsonObject message = messages.createNestedObject();
message["role"] = "user";
message["content"] = userContent;
String payload;
serializeJson(requestDoc, payload);
// 构建HTTP请求
String request = String("POST /v1/chat/completions HTTP/1.1\r\n") +
"Host: " + host + "\r\n" +
"Authorization: Bearer " + apiKey + "\r\n" +
"Content-Type: application/json\r\n" +
"Connection: close\r\n" +
"Content-Length: " + payload.length() + "\r\n\r\n" +
payload;
// 发送请求
Serial.println("[ESP32] 正在发送请求...");
client.print(request);
// 跳过响应头
while (client.connected() && client.available() == 0) delay(10);
while (client.available()) {
String line = client.readStringUntil('\n');
if (line == "\r") break;
}
// 处理分块响应
String responseBody = parseChunkedResponse(client);
client.stop();
return responseBody;
}
// 分块响应解析
String parseChunkedResponse(WiFiClientSecure &client) {
String body;
ChunkState state = PARSE_CHUNK_SIZE;
int chunkSize = 0;
unsigned long lastData = millis();
Serial.println("[ESP32] 开始接收分块数据...");
while (client.connected() && millis() - lastData < 60000) { // 60秒超时,注意:如果你的内容很多,超时时间要加长,不然还没思考完就超时了!!!
if (client.available()) {
lastData = millis();
switch (state) {
case PARSE_CHUNK_SIZE: {
String hexLine = client.readStringUntil('\r');
client.read(); // 跳过\n
chunkSize = strtol(hexLine.c_str(), NULL, 16);
Serial.printf("[ESP32] 块大小: %d\n", chunkSize);
if (chunkSize <= 0) {
state = PARSE_COMPLETE;
Serial.println("[ESP32] 接收到结束块");
} else {
state = PARSE_CHUNK_DATA;
}
break;
}
case PARSE_CHUNK_DATA: {
Serial.println("[ESP32] 接收块数据中...");
while (chunkSize > 0) {
if (client.available()) {
char c = client.read();
body += c;
chunkSize--;
lastData = millis(); // 每次接收重置超时
} else {
delay(10); // 避免CPU占用过高,自己看情况吧
}
}
client.read(); // 跳过\r
client.read(); // 跳过\n
state = PARSE_CHUNK_SIZE;
Serial.println("[ESP32] 块数据接收完成");
break;
}
case PARSE_COMPLETE:
Serial.printf("[ESP32] 接收完成,总长度: %d\n", body.length());
return body;
}
} else {
delay(50); // 降低CPU占用
}
}
Serial.println("[WARN] 分块接收超时");
return body;
}
// 响应解析
void parseApiResponse(String response) {
if (response.length() == 0) {
Serial.println("[ERROR] 收到空响应");
return;
}
Serial.println("[ESP32] 原始响应数据:");
Serial.println(response);
DynamicJsonDocument doc(8192); // 增大缓冲区,注意:这个是esp32能获取的数据,自己看情况!!!
DeserializationError error = deserializeJson(doc, response);
if (error) {
Serial.print("[ERROR] JSON解析失败: ");
Serial.println(error.c_str());
return;
}
if (doc.containsKey("error")) {
Serial.print("[ERROR] API错误: ");
serializeJson(doc["error"], Serial);
return;
}
if (doc.containsKey("choices")) {
const char* content = doc["choices"][0]["message"]["content"];
Serial.println("\n---------- DeepSeek回复 ----------");
Serial.println(content);
JsonObject usage = doc["usage"];
Serial.printf("\nToken使用: 总%d (输入%d + 输出%d)\n",
usage["total_tokens"].as<int>(),
usage["prompt_tokens"].as<int>(),
usage["completion_tokens"].as<int>());
Serial.println("--------------------------");
} else {
Serial.println("[ERROR] 响应格式异常");
}
}