Edited at

GoogleApps ScriptにESP8266からPOSTする

More than 1 year has passed since last update.

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;
}