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

ESP32通过Google App Script向Google Sheet传数据多次后连接失败如何解决

故障成因
  • 核心原因:全局定义的WiFiClientSecure对象未主动释放连接资源。ESP32的可用TCP socket数量上限通常为4~5个,你每次调用client.connect()后没有执行client.stop()主动销毁连接,即使HTTP头指定了Connection: close,底层socket资源仍会被占用,3~4次请求后socket被占满,后续连接自然失败。
  • 次要问题1:响应判断逻辑不匹配。GAS端返回的是纯文本success,但ESP32端判断逻辑为line.startsWith("{\"state\":\"success\""),永远会判定为请求失败,且你仅读取了第一行响应内容,剩余数据残留在client缓冲区,会干扰下一次请求的解析。
  • 次要问题2:HTTP方法使用不规范。用GET请求执行数据写入操作,部分场景下可能触发Google的缓存策略,导致请求被拦截。
可行解决方案

必改修复项

  1. 每次请求结束后强制释放连接资源
    在sendData函数的所有返回路径末尾添加client.stop(),确保不管请求成功还是失败,都释放socket资源。修改后sendData的示例代码:
void sendData(float SValue1, float SValue2) {
    Serial.println("==========");
    Serial.print("connecting to "); Serial.println(host);
    // 连接前先关闭旧连接,避免残留
    if(client.connected()){
        client.stop();
    }
    if (!client.connect(host, httpsPort)) {
        Serial.println("connection failed");
        client.stop(); // 连接失败也要释放资源
        return;
    }
    //---- Post Data 原有逻辑不变
    String url;
    url += "/macros/s/" + GAS_ID + "/exec?";
    url += "id=" + String(GAS_Sheet);
    url += "&temperature=" + String(SValue1, 2);
    url += "&humidity=" + String(SValue2, 2);
    Serial.print("requesting URL: "); Serial.println(url);
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
            "Host: " + host + "\r\n" +
            "User-Agent: BuildFailureDetectorESP8266\r\n" +
            "Connection: close\r\n\r\n");
    Serial.println("request sent");
    //---- Wait Echo 逻辑优化:读完所有响应头
    while (client.connected() || client.available()) {
        String line = client.readStringUntil('\n');
        if (line == "\r") {
            Serial.println("headers received");
            break;
        }
    }
    String line = client.readStringUntil('\n');
    // 修改判断逻辑和GAS返回对齐
    if (line == "success") {
        Serial.println("ESP-32 data upload successfull!");
    } else {
        Serial.println("ESP-32 data upload failed");
    }
    Serial.print("reply was : ");
    Serial.println(line);
    // 强制释放连接
    client.stop();
    Serial.println("closing connection");
    Serial.println("==========");
    Serial.println();
}
  1. 可选对齐GAS返回格式
    如果你不想修改ESP32的判断逻辑,可以修改GAS端返回JSON格式和原有代码对齐:
function doGet(e){
    // 原有逻辑完全不变
    var ss = SpreadsheetApp.getActive();
    var sheet = ss.getSheetByName(e.parameter["id"]);
    var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
    var lastRow = sheet.getLastRow();
    var cell = sheet.getRange('a1');
    var col = 0;
    var d = new Date();
    for (i in headers){
        if (headers[i] == "Timestamp") {
            val = d.toDateString() + ", " + d.toLocaleTimeString();
        } else {
            val = e.parameter[headers[i]];
        }
        cell.offset(lastRow, col).setValue(val);
        col++;
    }
    // 仅修改返回内容为JSON格式
    return ContentService.createTextOutput(JSON.stringify({"state":"success"})).setMimeType(ContentService.MimeType.JSON);
}

可选优化项

  • 将WiFiClientSecure改为sendData函数内的局部变量,每次请求新建对象,用完自动销毁,从根源避免资源残留问题。
  • 将GET请求改为POST请求传输数据,符合HTTP语义,同时避免Google缓存拦截。
  • 增加请求超时判断,避免长时间阻塞在响应读取步骤。

内容的提问来源于stack exchange,提问作者Jatu Tung

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:24:03