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

Arduino向Google Sheets上传数据时连接重定向URL失败求助

Arduino Google Sheets 上传连接故障排查

我正在开发一个向Google Sheets上传数据的Arduino项目,测试时仅能成功上传2-3次数据,之后连接断开,出现**"Connection to re-directed URL failed!"**错误。已尝试配置重连变量及相关逻辑,但问题仍未解决(首次处理Google Sheets的WiFi连接问题)。以下是项目相关代码及重连配置,寻求重连问题的解决指导。

重连变量

int error_count=0;
int connect_count=0;
const unsigned int MAX_CONNECT=20;
bool flag=false;

Setup函数中的连接配置

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while(WiFi.status()!=WL_CONNECTED){
  Serial.print(".");
  delay(500);
}
Serial.println();
Serial.println("Conexión Wi-Fi establecida");
client = new HTTPSRedirect(httpsPort);
client->setInsecure();
client->setPrintResponseBody(true);
client->setContentTypeHeader("application/json");
delay(5000);
Serial.print("Connecting to ");
Serial.println(host);
bool flag = false;
for(int i=0; i<5; i++){ 
  int retval=client->connect(host, httpsPort);
  if (retval==1){
    flag = true;
    String msg = "Connected. OK";
    Serial.println(msg);
    delay(2000);
    break;
  }
  else
    Serial.println("Connection failed. Retrying...");
}
if (!flag){
  Serial.print("Could not connect to server: ");
  Serial.println(host);
  delay(5000);
  return;
}
delete client;
client=nullptr;

Loop函数中的重连配置

if(!flag){
  client=new HTTPSRedirect(httpsPort);
  client->setInsecure();
  flag=true;
  client->setPrintResponseBody(true);
  client->setContentTypeHeader("application/json"); 
}
if(client!=nullptr){
  if(!client->connected()){
    int retval=client->connect(host, httpsPort);
    if(retval!=1){
      Serial.println("Disconnected. Retrying...");
      flag=false;
      return;
    }
  }
}
else{
  Serial.println("¡Error al crear el objeto del cliente!");
  error_count=5;
}
if(connect_count>MAX_CONNECT){
  connect_count=0;
  flag=false;
  delete client;
  return;
}
/*if(client->GET(url1, host)){
  payload1 = client->getResponseBody();
  payload1.trim();
  ++connect_count;
}
if(client->GET(url2, host)){
  payload2=client->getResponseBody();
  payload2.trim();
  ++connect_count;
}*/
if (error_count>3){
  Serial.println("Procesador detenido...");
  delete client;
  client=nullptr;
}
delay(1000);
//int Fecha1=payload1.toInt();
//int Fecha2=payload2.toInt();
//Serial.println(Fecha1);
//Serial.println(Fecha2);
SendData(Upload_Data);

SendData函数

void SendData(String value){
  String Implementation_ID="AKfycbySelLW32HKb-xTacKpxFi9nP-9iKtQKnnumD5mJVVzR7CmNfuDq9vwiBAO5mw31FVrMQ";
  String URL=String("/macros/s/")+Implementation_ID+"/exec";
  payload=payload_base+"\""+1.00+","+1+","+1+"\"}";
  Serial.println("Subiendo datos...");
  Serial.println(payload);
  if(client->POST(URL, host, payload)){
    client->stop();
  }
  delay(5000);
}

完整项目代码

//Librerias
///AKfycbySelLW32HKb-xTacKpxFi9nP- 
9iKtQKnnumD5mJVVzR7CmNfuDq9vwiBAO5mw31FVrMQ->Datos recibidos en Sheets
///AKfycbyJDxdFaR4FuMMD2fOfhXZWdX2ZlIBfjteY4pwePI1NuQVi4eE-uM0-lWppz-EH1sM->Datos enviados de la prueba
#include <Arduino.h>
#include <MD_MAX72xx.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <esp_crt_bundle.h>
#include <ssl_client.h>
#include <DebugMacros.h>
#include <HTTPSRedirect.h>
//Defines tiempos
#define  DELAYTIME  100 //in milliseconds
#define  DELAYTIME2 500
//Defines pines
#define MAX_DEVICES  4
#define CHAR_SPACING 1
#define CLK_PIN      18 //or SCK
#define DATA_PIN     23 //or MOSI
#define CS_PIN       5 //or SS
#define SCK          14
#define MISO         27
#define MOSI         13
#define CS           15
//Defines variables
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//Variables utilizando las librerias
SPIClass spi0=SPIClass(HSPI);
MD_MAX72XX mx=MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
HTTPSRedirect* client=nullptr;
//Variables
int error_count=0;
int connect_count=0;
const unsigned int MAX_CONNECT=20;
const int httpsPort=443;
const char *ssid="FAMILIA FARFAN";
const char *password="Jejmpn199020";
const char *host="script.google.com";
const char *GScriptId="AKfycbyJDxdFaR4FuMMD2fOfhXZWdX2ZlIBfjteY4pwePI1NuQVi4eE-uM0-lWppz-EH1sM"; //Recibiendo datos desde google sheets (dirección de script)
const char *cellAddress1="A1";
const char *cellAddress2="A2";
String payload_base = "{\"command\": \"insert_row\", \"sheet_name\":\"HojadeDatos\", \"values\": ";
String url1=String("/macros/s/") + GScriptId + "/exec?read=" + cellAddress1;
String url2=String("/macros/s/") + GScriptId + "/exec?read=" + cellAddress2;
String payload="";
String payload1="";
String payload2="";
String Upload_Data="";
bool flag=false;
void setup(){
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  spi0.begin(SCK, MISO, MOSI, CS);
  mx.begin();
  Serial.print("Conectando a la red Wi-Fi");
  while(WiFi.status()!=WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.println("Conexión Wi-Fi establecida");
  if(!SD.begin(CS, spi0)){
    Serial.println("Card Mount Failed");
    return;
  }
  client = new HTTPSRedirect(httpsPort);
  client->setInsecure();
  client->setPrintResponseBody(true);
  client->setContentTypeHeader("application/json");
  delay(5000);
  Serial.print("Connecting to ");
  Serial.println(host);
  bool flag = false;
  for(int i=0; i<5; i++){ 
    int retval=client->connect(host, httpsPort);
    if (retval==1){
      flag = true;
      String msg = "Connected. OK";
      Serial.println(msg);
      delay(2000);
      break;
    }
    else
      Serial.println("Connection failed. Retrying...");
  }
  if (!flag){
    Serial.print("Could not connect to server: ");
    Serial.println(host);
    delay(5000);
    return;
  }
  delete client;
  client=nullptr;
  uint64_t cardSize=SD.cardSize()/(1024*1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.printf("Total space: %lluMB\n", SD.totalBytes()/(1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes()/(1024 * 1024));
}

void loop(){
  while(true){
    char buff[9]={72, 111, 108, 97, 97, 97, 97, 97};
    int val1=1;
    int val2=1;
    int val3=1;
    if(!SD.exists("/hello.csv")){
      createFile(SD, "/hello.csv");
    }
    scrollText(buff);
    appendFile(SD, "/hello.csv", val1, val2, val3);
    readFile(SD, "/hello.csv");
    if(!flag){
      client=new HTTPSRedirect(httpsPort);
      client->setInsecure();
      flag=true;
      client->setPrintResponseBody(true);
      client->setContentTypeHeader("application/json"); 
    }
    if(client!=nullptr){
      if(!client->connected()){
        int retval=client->connect(host, httpsPort);
        if(retval!=1){
          Serial.println("Disconnected. Retrying...");
          flag=false;
          return;
        }
      }
    }
    else{
      Serial.println("¡Error al crear el objeto del cliente!");
      error_count=5;
    }
    if(connect_count>MAX_CONNECT){
      connect_count=0;
      flag=false;
      delete client;
      return;
    }
    /*if(client->GET(url1, host)){
      payload1 = client->getResponseBody();
      payload1.trim();
      ++connect_count;
    }
    if(client->GET(url2, host)){
      payload2=client->getResponseBody();
      payload2.trim();
      ++connect_count;
    }*/
    if (error_count>3){
      Serial.println("Procesador detenido...");
      delete client;
      client=nullptr;
    }
    delay(1000);
    //int Fecha1=payload1.toInt();
    //int Fecha2=payload2.toInt();
    //Serial.println(Fecha1);
    //Serial.println(Fecha2);
    SendData(Upload_Data);
  }
}
void scrollText(char *p){
  uint8_t charWidth;
  uint8_t cBuf[8];
  mx.clear();
  while(*p!='\0'){
    charWidth = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
    for(uint8_t i=0; i<=(charWidth); i++){
      mx.transform(MD_MAX72XX::TSL);
      if (i<charWidth)
        mx.setColumn(0, cBuf[i]);
      delay(DELAYTIME);
    }
  }
  delay(DELAYTIME);
}
void createFile(fs::FS &fs, const char * path){
  Serial.printf("Creando archivo: %s\n", path);
  File file = fs.open(path, FILE_WRITE);
  if(file){
    file.close();
  }
  else{
    Serial.println("Error archivo");
  }
}
void readFile(fs::FS &fs, const char * path){
  Serial.printf("Leyendo archivo: %s\n", path);
  File file = fs.open(path);
  if(!file){
    Serial.println("Error al abrir el archivo para leer.");
    return;
  }
  while(file.available()){
    Upload_Data=Upload_Data+file.readString();
  }
  file.close();
}
void deleteFile(fs::FS &fs, const char * path){
  Serial.printf("Eliminando archivo: %s\n", path);
  if(fs.remove(path)){
    Serial.println("Archivo eliminado.");
  } else {
    Serial.println("Error al eliminar el archivo.");
  }
}
void appendFile(fs::FS &fs, const char * path, int message, int message1, int message2){
  File file = fs.open(path, FILE_APPEND);
  if(file){
    file.print(message);
    file.print(",");
    file.print(message1);
    file.print(",");
    file.println(message2);
    file.close();
  }
  else{
   Serial.println("Error al abrir archivo.");
  }
}
void SendData(String value){
  String Implementation_ID="AKfycbySelLW32HKb-xTacKpxFi9nP-9iKtQKnnumD5mJVVzR7CmNfuDq9vwiBAO5mw31FVrMQ";
  String URL=String("/macros/s/")+Implementation_ID+"/exec";
  payload=payload_base+"\""+1.00+","+1+","+1+"\"}";
  Serial.println("Subiendo datos...");
  Serial.println(payload);
  if(client->POST(URL, host, payload)){
    client->stop();
  }
  delay(5000);
}

问题分析与解决建议

1. 强制关闭连接破坏重定向处理

SendData函数中每次POST后调用client->stop(),会直接断开连接,而Google Scripts经常返回3xx重定向,HTTPSRedirect客户端需要自动处理重定向流程,手动关闭会导致后续连接失败。

修复:移除client->stop(),并在上传失败时标记重连:

void SendData(String value){
  String Implementation_ID="AKfycbySelLW32HKb-xTacKpxFi9nP-9iKtQKnnumD5mJVVzR7CmNfuDq9vwiBAO5mw31FVrMQ";
  String URL=String("/macros/s/")+Implementation_ID+"/exec";
  payload=payload_base+"\""+1.00+","+1+","+1+"\"}";
  Serial.println("Subiendo datos...");
  Serial.println(payload);
  
  if(!client->POST(URL, host, payload)){
    flag = false;
    error_count++;
  } else {
    error_count = 0;
  }
  delay(5000);
}

2. 局部变量覆盖全局flag

setup函数中定义了局部bool flag = false;,覆盖了全局flag变量,导致loop中的重连逻辑失效。

修复:删除setup中的局部flag声明,直接使用全局变量:

// setup函数内修改
flag = false;
for(int i=0; i<5; i++){ 
  int retval=client->connect(host, httpsPort);
  if (retval==1){
    flag = true;
    String msg = "Connected. OK";
    Serial.println(msg);
    delay(2000);
    break;
  }
  else
    Serial.println("Connection failed. Retrying...");
}

3. 未处理WiFi断开场景

当前仅检查客户端连接状态,未检查WiFi本身是否掉线,若WiFi断开,客户端连接检查会失效。

修复:在loop中添加WiFi状态检查:

// loop的重连逻辑前添加
if(WiFi.status() != WL_CONNECTED){
  Serial.println("WiFi disconnected, reconnecting...");
  WiFi.reconnect();
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi reconnected");
  flag = false;
}

4. Upload_Data内存泄漏

readFile函数中持续向Upload_Data追加内容,未清空旧数据,导致字符串无限膨胀,占用过多内存。

修复:每次读取文件前清空Upload_Data:

void readFile(fs::FS &fs, const char * path){
  Serial.printf("Leyendo archivo: %s\n", path);
  Upload_Data.clear();
  File file = fs.open(path);
  if(!file){
    Serial.println("Error al abrir el archivo para leer.");
    return;
  }
  while(file.available()){
    Upload_Data=Upload_Data+file.readString();
  }
  file.close();
}

5. 客户端对象频繁创建导致内存泄漏

当前逻辑频繁创建和删除HTTPSRedirect对象,易引发内存泄漏,建议复用对象,仅在连接失败时重建。

优化:调整loop中的客户端初始化逻辑:

// loop中修改
if(client
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:18:25