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
相关产品推荐
相关产品推荐

