ESP8266/ESP32でGoogleSpreadSheetのセルを更新する

ESP8266/ESP32でGoogleSpreadSheetのセルを更新するならIFTTTがあります。
僕は今後の事も考えてGoogle Apps Scriptで更新することにしました。
Google Apps Scriptは、Googleサービスに対して色々出来そうなので、
ESP8266からのアクセス方法を知っておくのは良さそうです。

#使うもの
　　ArduinoIDE - ESP8266/ESP32
　　Google Apps Script
　　Google Spreadsheet
　　Sujay Phadkeさん作   HTTPSRedirect [リンク](https://github.com/electronicsguy/ESP8266/tree/master/HTTPSRedirect)

　　HTTPSRedirectは任意のセルを更新するサンプルが無いので作ってみました。

#ESP8266/ESP32からGoogle Apps Scriptを呼ぶ
　GScriptId = Script作成で紹介されるIDをセットします。
　JSON形式データ = Scriptのfunction doPost(e)コードを見れば判ると思います
　　command = 'cellUpdate'　　コマンド名です
　　sheet_id　　　　　　　　　　スプレッドシートIDです。
　　sheet_name　　　　　　　　　シート名です。　（全角文字未対応）
　　cellPosition　　　　　　　　更新するセルの位置です
　　values　　　　　　　　　　　更新内容です。
　　　　　　　　　　　　　　　　 Scriptの内容だと、一度で複数のセルを更新することもできますね。
  
#ESP32で使う方法
　　HTTPSRedirect.hソースでコメントされているstop()を動作する様にします。
    //stop(); // may not be required

#Google Scriptのソース
```js:GoogleScript.gs
function onOpen(){
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('ESP8266 Logging')
  .addItem('Clear', 'Clear')
  .addToUi();
}

function Clear(){
  sheet.deleteRows(4, sheet.getLastRow());
  SS.toast('Chart cleared', 'ESP8266 logging', 5);
}

function doPost(e) 
{
  var parsedData;
  try { parsedData = JSON.parse(e.postData.contents); } 
  catch(f){ return ContentService.createTextOutput("JSONデータの解釈が出来ません。: " + f.message);　}

  if (　parsedData.command !== "cellUpdate" )
  {
    return ContentService.createTextOutput("Error! Request body empty or in incorrect format.");
  }

  var spreadSheetID = SpreadsheetApp.openById(parsedData.sheet_id);
  var sheet         = spreadSheetID.getSheetByName(parsedData.sheet_name);
  var cellPosition  = parsedData.cellPosition;
  sheet.getRange(cellPosition).setValue(parsedData.values);
  SpreadsheetApp.flush();
  return ContentService.createTextOutput( "Success" );
}

function doGet(e){
    return ContentService.createTextOutput("unknown" + e.parameter.value);
}
```


#ESP8266のソース
loop関数の中で更新していますが、ここまでやった関数化しても良さそうですね。

```cpp:
#include <ESP8266WiFi.h>
#include "HTTPSRedirect.h"

// Fill ssid and password with your network credentials
const char* ssid = "guest";
const char* password = "guest";

const char* host = "script.google.com";
const int httpsPort = 443;
// Replace with your own script id to make server side changes

// google scriptのscriptID
const char *GScriptId = "＝＝google SciptIDをセットします＝＝";

// Fetch Google Calendar events for 1 week ahead
const String url = String("/macros/s/") + GScriptId+ "/exec?value=Hello";
const String payload_base_cell =      "{\"command\": \"cellUpdate\", \"cellPosition\": \"";
const String payload_base_sheetid =    "\",\"sheet_id\": \"";
const String payload_base_sheetname =  "\",\"sheet_name\": \"";
const String payload_base_values =     "\",\"values\": ";
const String payload_base_terminate =  "\"}";

String payload = "";

HTTPSRedirect* client = nullptr;

void setup() {
  Serial.begin(115200);
  Serial.print("Connecting to wifi: ");  Serial.println(ssid);
  Serial.flush();

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("IP address: ");  Serial.println(WiFi.localIP());
}

int count;

void loop() {
bool flag;
char stringCount[10];
  sprintf( stringCount, "%d", count);
  count++;
  // Use HTTPSRedirect class to create a new TLS connection
  client = new HTTPSRedirect(httpsPort);
  client->setPrintResponseBody(true);
  client->setContentTypeHeader("application/json");
  Serial.print("Connecting to ");  Serial.println(host);
  // Try to connect for a maximum of 5 times
  flag = false;
  for (int i=0; i<5; i++){
    int retval = client->connect(host, httpsPort);
    if (retval == 1) {
       flag = true;
       break;
    }
    else
      Serial.println("Connection failed. Retrying...");
  }
  if (!flag){
    Serial.print("Could not connect to server: ");
    Serial.println(host);
    Serial.println("Exiting...");
    return;
  }
  // Send memory data to Google Sheets
  payload = payload_base_cell + "G6";
  payload = payload + payload_base_sheetid + "＝＝Google SpreadsheetのIDをセットします＝＝";
  payload = payload + payload_base_sheetname + "sheet1";
  payload = payload + payload_base_values + "\"" + stringCount + payload_base_terminate;
  Serial.println("==POSTCOMMAND==============================");
  Serial.println( payload );
  client->POST(url, host, payload, false);
  Serial.println("==POSTCOMMAND==============================");
  // delete HTTPSRedirect object
  delete client;
  client = nullptr;

  delay(60000);
}
```
昔は
　　本当はESP32対応のArduinoIDEソースで作りたかったのですけど、動きそうなソースなのに動かない。
　　僕はHTTPSをマトモに理解していないので、断念しました～　＞＜

今は
　　HTTPSRedirectがESP32に対応してくれてます。
　　私のESP8266向けコードも周辺コードをESP32化するだけで動作しました。
　　サンプルソースはESP8266向けですがinclude文を変更する程度でESP32も動作すると思います
　　VisualStudio2010Express版のC#のWebBrowserコントロールでも動作を確認しました。