当前位置: 首页 > news >正文

实现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] 响应格式异常");

  }

}

相关文章:

  • 【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的安全性:使用 Spring Security 实现认证与授权
  • React 中的 Props
  • 文件操作与IO—文件读写
  • 开源手机号码价值评估系统
  • AI Agent系列(八) -基于ReAct架构的前端开发助手(DeepSeek)
  • Spring笔记04-注解注入
  • Python每日一题(11)
  • oracle执行计划
  • 《异常检测——从经典算法到深度学习》30. 在线服务系统中重复故障的可操作和可解释的故障定位
  • 42. 接雨水
  • Flutter敏感词过滤实战:基于AC自动机的高效解决方案
  • 二分查找:原理、循环不变量与边界处理
  • 设置网站主题色color-scheme
  • 【Easylive】HttpServletRequest、HttpServletResponse、HttpSession 介绍
  • Leetcode hot 100刷题之路(day 1)
  • 黑盒测试的场景法(能对项目业务进行设计测试点)
  • ngx_monotonic_time
  • Git Fetch 和 Git Pull 的区别
  • 双层板模组天线设计指南,50欧姆阻抗匹配设计
  • B-tree 索引失效 避坑指南
  • 个人微商城怎么开通/上海aso优化公司
  • 世界500强企业logo图片/潍坊关键词优化软件
  • 哈尔滨网站运营服务商/网站站长
  • 本网站服务器在美国维/seo优化培训公司
  • 网站站内链接怎么做/人际网络营销2900
  • 网站建设话术开场白/注册百度账号