【问题标题】:Problem ESP32 send data to Google Sheet through Google App Script问题 ESP32 通过 Google App Script 向 Google Sheet 发送数据
【发布时间】:2021-10-23 06:49:06
【问题描述】:

起初,我的问题来自我的小项目 IoT。目的,使用 ESP32 通过 Google App Script 向 Google Sheet 发送数据。

ESP32的任务是取两个随机数,通过http方式通过Google App Script(Web App)传给Google Sheet。

我的问题是,在 ESP32 和 Google App Script 之间的连接每次都失败之后,我只能向 Google Sheet 插入数据 3-4 条记录。我不确定这个问题。

我的代码有两部分,第一部分用于 ESP32 (Arduino IDE),第二部分用于 Google App Script

第一部分代码如下,很简单。

#include <WiFi.h>
#include <WiFiClientSecure.h>
String t;
const char* host = "script.google.com";
const int httpsPort = 443;
const char* ssid = "MY_SSID";
const char* pass = "MY_SSID_PW";
String GAS_ID = "GAS_ID";
String GAS_Sheet = "dht_data";
WiFiClientSecure client;
long now = millis();
long lastMeasure = 0;
void setup() {
    Serial.begin(115200); delay(500);
    WiFi.begin(ssid, pass);
    Serial.print("\nConnecting");
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
    }
    Serial.print("\nSuccessfully connected to : "); Serial.println(ssid);
    Serial.print("\nIP address: "); Serial.println(WiFi.localIP());
    Serial.println();
    client.setInsecure();
}
void loop() {
    now = millis();
    if (now - lastMeasure > 30000) {
        lastMeasure = now;
        float ValueSensor1 = random(2000, 4000) / 100.0;
        float ValueSensor2 = random(6000, 8000) / 100.0;
        Serial.println();
        Serial.print("\ntemperature = "); Serial.print(ValueSensor1, 1);
        Serial.print("\thumidity = "); Serial.print(ValueSensor2, 1);
        Serial.println();
        sendData(ValueSensor1, ValueSensor2);
    }
}
void sendData(float SValue1, float SValue2) {
    Serial.println("==========");
    Serial.print("connecting to "); Serial.println(host);
    //---- Connect to Google host
    if (!client.connect(host, httpsPort)) {
        Serial.println("connection failed");
        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()) {
        String line = client.readStringUntil('\n');
        if (line == "\r") {
            Serial.println("headers received");
            break;
        }
    }
    String line = client.readStringUntil('\n');
    if (line.startsWith("{\"state\":\"success\"")) {
        Serial.println("ESP-32/Arduino CI successfull!");
    } else {
        Serial.println("ESP-32/Arduino CI has failed");
    }
    Serial.print("reply was : ");
    Serial.println(line);
    Serial.println("closing connection");
    Serial.println("==========");
    Serial.println();
}

第二部分代码如下,

function doGet(e){
    // open the spreadsheet
    var ss = SpreadsheetApp.getActive();

    // use the 'id' parameter to differentiate between sheets
    var sheet = ss.getSheetByName(e.parameter["id"]);

    // extract headers
    // getRange accepts row, col, number_of_rows and num_of_cols as argument
    // getLastColumn returns the position of the last column that has content
    var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];

    // store the position of the last row
    var lastRow = sheet.getLastRow();
    var cell = sheet.getRange('a1');
    var col = 0;
    var d = new Date();
    for (i in headers){
        // loop through the headers and if a parameter name matches the header name insert the value
        if (headers[i] == "Timestamp") {
            val = d.toDateString() + ", " + d.toLocaleTimeString();
        } else {
            val = e.parameter[headers[i]];
        }
        // append data to the last row
        cell.offset(lastRow, col).setValue(val);
        col++;
    }
    return ContentService.createTextOutput('success');
}

问题的原因是什么?以及如何解决?

非常感谢您。

【问题讨论】:

  • 正如我的猜测,我提出了一个答案。你能确认一下吗?如果这不是您问题的直接解决方案,我深表歉意。
  • @Jatu Tung,请编辑问题以包含 ESP32 的输出,包括任何崩溃/启动消息。我们需要知道这是如何失败的,而不仅仅是它失败了。有许多不同的事情可能会出错。输出将有助于缩小“失败”的含义。

标签: google-apps-script google-sheets esp32 arduino-esp32


【解决方案1】:

这只是我的猜测。来自My problem is, I can insert data to Google Sheet only 3-4 records, after that connection between ESP32 and Google App Script has failed everytime. I am not sure about the problem.,我担心将数据发送到 Web 应用程序的频率。我认为当数据不断发送到Web Apps时,可能会出现这样的错误。那么在这种情况下,下面的修改呢?

修改脚本:

在此修改中,我降低了您的 Google Apps Script for Web Apps 的处理成本,并添加了 LockService。

function doGet(e) {
  const lock = LockService.getDocumentLock();
  if (lock.tryLock(350000)) {
    try {
      var sheet = SpreadsheetApp.getActive().getSheetByName(e.parameter["id"]);
      var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
      var d = new Date();
      var values = headers.map(h => h == "Timestamp" ? d.toDateString() + ", " + d.toLocaleTimeString() : e.parameter[h]);
      sheet.getRange(sheet.getLastRow() + 1, 1, 1, values.length).setValues([values]);
    } catch (e) {
      return ContentService.createTextOutput(JSON.stringify(e));
    } finally {
      lock.releaseLock();
      return ContentService.createTextOutput('success');
    }
  } else {
    return ContentService.createTextOutput("timeout");
  }
}

注意:

  • 当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
  • 您可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中查看详细信息。
  • 在我最近的报告中,当Web Apps的脚本处理成本较低时,Web Apps可以做大约60个并发访问。 Ref 但是,你这种情况的流程成本,我从来没有测过。所以我不确定这是否是您问题的直接解决方案。

参考资料:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多