7
9

More than 5 years have passed since last update.

GoogleApps ScriptにESP8266からPOSTする

Last updated at Posted at 2018-08-11

Google Apps Script (GAS)に定期的にデータを上げるための開発メモ。

ポイント1

定期実行はArduinoのMsTimer2の代わりにTickerライブラリを使う

サンプルコード

TickerTest.ino
#include <Ticker.h>

Ticker ticker;
bool bSend = false;

void setup() {
  ticker.attach_ms(1000, onTicker);
}

void loop() {
  if (bSend) {
    //GASへPOSTする処理

    bSend = false;
  }
}

void onTicker() {
  bSend = true;
}

ポイント2

GASへ送る方法

準備1:fingerprintを取得

  1. opensslをインストール
  2. powerdhellでecho | .\openssl s_client -connect script.google.com:443 |& .\openssl x509 -fingerprint -nooutを実行
  3. `const char* fingerprint = "XX:XX:XX:.....:XX";とする

準備2:GASでdoPost(e)なコードを用意する

  • concole.log(e.postData.contents)とかやればとりあえすStackdriverのログに残ると思う
  • json.parseとかでjsonをパースできるね

GASのサンプルコード

コード.gs
function doPost(e) {
  console.log(e.postData.contents); //Stackdriverのログへ
}

サンプルコード

https://github.com/electronicsguy/ESP8266/tree/master/HTTPSRedirect
のGooggleDocs.inoの改変です(サンプルがとても複雑なので)

コードに残っている課題

  • HTTPSRedirectのオブジェクト確保まわり
  • メモリを食いつぶしてwdtで落ちる問題とか
  • たまに送信できなくなる
GAStest.ino
#include <ESP8266WiFi.h>
#include "HTTPSRedirect.h"
#include "DebugMacros.h"

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

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

String url = String("/macros/s/") + GScriptId + "/exec";

const int httpsPort = 443;

// echo | openssl s_client -connect script.google.com:443 |& openssl x509 -fingerprint -noout
const char* fingerprint = "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX";

HTTPSRedirect* client = nullptr;
bool bClient = false;
const int MAX_CONNECT = 20;
int error_count = 0;
int connect_count = 0;

bool bSend;

//Ticker timer lib
Ticker ticker;
static const int TIMER_DELAY = 30 * 1000;

void setup() {
  //start serial
  Serial.begin(115200); //for debug
  Serial.println("");
  Serial.flush();

  wifiMulti.addAP("****", "*****");

  //start timer
  ticker.attach_ms(TIMER_DELAY, onTimer);
  Serial.println("setup end");
}

void loop() { //nothing again...
  static wl_status_t prevWifiStatus = WL_IDLE_STATUS;
  wl_status_t wifiStatus = wifiMulti.run();
  if ( prevWifiStatus != wifiStatus ) {
    prevWifiStatus = wifiStatus;
    if ( wifiStatus == WL_CONNECTED) {
      Serial.println("WiFi connected");
      Serial.print("SSID: ");
      Serial.println(WiFi.SSID());
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    }
    else {
      Serial.print("WiFi error: ");
      switch(wifiStatus){
        case WL_NO_SHIELD:
          Serial.println("WL_NO_SHIELD");
          break;
        case WL_IDLE_STATUS:
          Serial.println("WL_IDLE_STATUS");
          break;
        case WL_NO_SSID_AVAIL:
          Serial.println("WL_NO_SSID_AVAIL");
          break;
        case WL_SCAN_COMPLETED:
          Serial.println("WL_SCAN_COMPLETED");
          break;
        case WL_CONNECT_FAILED:
          Serial.println("WL_CONNECT_FAILED");
          break;
        case WL_CONNECTION_LOST:
          Serial.println("WL_CONNECTION_LOST");
          break;
        case WL_DISCONNECTED:
          Serial.println("WL_DISCONNECTED");
          break;
      }

    //wifiがつながってなかったらloopを抜けて送信をしない
    return;
    }
  }

  if (!bSend) return;
  Serial.println("Send Start.");

  if (!bClient) {
    client = new HTTPSRedirect(httpsPort);
    bClient = true;
    client->setPrintResponseBody(true);
    client->setContentTypeHeader("application/json");
  }

  if (client != nullptr) {
    if (!client->connected()) {
      client->connect(host, httpsPort);
    }
  }
  else {
    Serial.println("Error creating client object!");
    error_count = 5;
    return;
  }

  String payload = "{ \"value1\" : \"12345\" , \"humidity\" : \"67890\"}";
  if (client->POST(url, host, payload, false)) {
    Serial.println("loop POST");
    connect_count++;
  }
  else {
    ++error_count;
    Serial.print("Error-count while connecting: ");
    Serial.println(error_count);
  }

  if (connect_count > MAX_CONNECT) {
    //error_count = 5;
    connect_count = 0;
    bClient = false;
    delete client;
    return;
  }

  if (error_count > 3) {
    Serial.println("Halting processor...");
    delete client;
    client = nullptr;
    Serial.flush();
    ESP.deepSleep(0);
  }

  bSend = false;
  Serial.println("Send Finished.");
}

void onTimer() {
  Serial.println("plz Send.");
  bSend = true;
}
7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9