You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32 Websocket服务器仅接收首个数据包问题求助

ESP32 Websocket服务器重复接收图像数据失败排查

我的项目基于ESP32与Websocket实现:带摄像头的ESP32作为服务器将图像数据转发至移动端,移动端可正常接收并在网页显示图像;随后移动端需将数据包转发至另一台作为Websocket服务器的ESP32,由其在TFT屏显示图像。

当前遇到的问题:

  • 仅能接收首张图像,之后移动端抛出Websocket连接失败错误,但移动端与ESP32均未主动关闭连接
  • 调整定时器/延迟后,移动端可转发更多数据包,但ESP32无接收反馈(串口监视器无相关输出)

我已查阅资料,了解readBlocking与readNonBlocking的区别,但所用的ArduinoWebsockets库仅支持readBlocking;网上同类项目(同ESP32、同库)可重复接收Websocket数据,且代码与我的相似,暂未定位问题。

请协助排查Websocket协议使用是否有误,或代码中是否存在问题。

附Arduino IDE编写的代码:

#include <SPIFFS.h>
#include <SPI.h>

#include <ArduinoWebsockets.h>
#include <WiFi.h>

#include <TJpg_Decoder.h>
#include <TFT_eSPI.h>

const char* ssid = "ssid_here";
const char* password = "password_here";
const char* imageFileName = "/camimage.jpeg";

using namespace websockets;
WebsocketsServer server;
WebsocketsClient client;

TFT_eSPI tft = TFT_eSPI();         // 调用自定义库
boolean SDInited = false;

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
   // 当图像超出屏幕底部时停止解码
  if ( y >= tft.height() ) return 0;

  // 该函数会自动在TFT边界处裁剪图像块进行渲染
  tft.pushImage(x, y, w, h, bitmap);

  // 返回1继续解码下一个块
  return 1;
}


void setup() {
  // 初始化代码,仅运行一次
  Serial.begin(115200);
  while(!Serial);
  delay(1000);

  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFS初始化失败!");
    while(1) yield();
  }else{
    SDInited = true;
    Serial.println("SPIFFS初始化成功");
  } 

  Serial.println("开始连接WiFi");
  WiFi.begin(ssid, password); // 初始化WiFi连接
  delay(500);

    for(int i = 0; i < 15 && WiFi.status() != WL_CONNECTED; i++) {
      Serial.print(".");
      delay(1000);
  }

  IPAddress IP = WiFi.localIP(); // 定义IP变量用于检查
  Serial.print("IP地址 : ");
  Serial.println(IP); // 打印IP地址用于Websocket连接
  
  Serial.println("初始化TFT屏幕");
  delay(1000);
  tft.begin(); // 初始化TFT
  tft.setRotation(3); // 横屏模式
  tft.fillScreen(random(0xFFFF)); // 屏幕填充随机颜色
  delay(1000);
  Serial.flush(); // 清空串口缓冲区
  delay(1000);
  tft.setSwapBytes(true); // 交换颜色字节提升图像清晰度

  TJpgDec.setJpgScale(1); // 不改变缩放比例

  TJpgDec.setCallback(tft_output); // 设置解码器的渲染回调函数
  
  server.listen(80); // WebSocket监听端口80

  // 检查服务器是否可用,并在串口监视器输出结果
  Serial.print("服务器是否可用? -> ");
  if(server.available()!=0){
    Serial.println("是");
  }
  else
  { 
    Serial.println("否");
  }
       
}

void loop() {
  // 主循环代码,重复运行

  Serial.println("进入循环...");
  if(SDInited){
    Serial.println("SPIFFS已初始化");
    WebsocketsClient client = server.accept(); // 接受连接
    
    if(client.available()){

      WebsocketsMessage msg = client.readBlocking(); // 读取接收到的数据到msg
      boolean isSaved = fileWrite(imageFileName, msg); // 将msg和文件名传入fileWrite函数保存
      if(isSaved){

        Serial.println(msg.data()); // 在串口监视器打印数据用于检查
        uint32_t t = millis();
        Serial.println(t); // 在串口监视器打印时间戳用于检查

        // 获取接收到的图像的宽高像素值
        uint16_t w = 0, h = 0;
        TJpgDec.getFsJpgSize(&w, &h, imageFileName); // 注意文件名前需加"/"
        Serial.print("宽度 = "); Serial.print(w); Serial.print(", 高度 = "); Serial.println(h);
      
        TJpgDec.drawFsJpg(0, 0, imageFileName); // 在TFT屏幕绘制图像

      }
  }
 }
}

boolean fileWrite(String name, WebsocketsMessage content){
  SPIFFS.remove("/camimage.jpeg");
  File file = SPIFFS.open(name.c_str(), "w");
  if(!file){
    String errorMsg = "无法打开文件";
    Serial.println(errorMsg);
    return false;
  }else{
    file.write((const uint8_t*) content.c_str(), content.length());
    file.close();
    return true;
  }
}

内容的提问来源于stack exchange,提问作者T Franklin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:43:19