0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IoTデバイスがGASからデータを"受信"する方法

Posted at

!!ご注意!!

この記事はIoT素人が自分の目的を達成するためにテキトウに調べて実践したことをテキトウにまとめています。間違った情報や非効率的な情報が混ざっている可能性があります!

それでもいいよって方は、ゆっくりしていってね

本題

みょんなことからIoTデバイス(ESP32)とGASを活用した模擬製品開発をすることとなった。
IoTデバイスとGASの活用例といえば、温度センサなどのデータを一定時間ごとにスプレッドシートに記録するというものをよく見かける。
これはIoTデバイスがGASにデータを送信する例と言えよう。

赤矢印が測定データの流れみたいな感じで描いてみた

では、受信はどうやってやればいいのだろうか?
例えば何かのセンサーのデータによってサーボモーターを動かすとか止めるとかしたいとする。このときセンサーとサーボは別々のIoTデバイスに接続されているとする。
image.png
用途は意味不明だがまあ仮にこんな構成があったとする。(温度センサーで測った値を丸形の温度計で再現するのだろうか?)

送信の場合、GASはいつでも待っていてくれるので任意のタイミングでhttps://script.google.com/macros/s/hogefuga/execHTTPリクエストのGETやPOSTを投げてやればできる。
では受信はどうしようか?鯖立てなんてしたらもはやそれはIoTの域を超えている気がする

ここで思いつく。
HTTPリクエストがあるのならその応答のHTTPレスポンスもあるのでは?
どうやらGASではdoGet()またはdoPost()の最後でContentService.createTextOutput()やHtmlService.createHtmlOutput()をreturnしてやればHTTPレスポンスを応答できるようだ。
つまり、受信側ではダミーのGETまたはPOSTを定期的に送り付けて、それを受けたGASにレスポンスとして必要なデータを返してもらえばいいのだ。
image.png

実装

AppsScriptの コード.gs
function doGet(e){
    var params = e.parameter; //URLの?name=value&name2=value2のようなものを取得
    var dummy=params.dummy; //dummy= の値を取得。未指定ならundefinedになる
    //var name=params.name; //必要に応じてGETリクエストで受け取るほかの変数も定義しておく
    if(dummy!==undefined){ //dummyに何かしらの値が設定されているとき=受信したがっている
        var sendtext=sheet.getRange("A1").getValue(); //例えばA1に送信したいデータが書き込まれているとき
        /*
        var response = ContentService.createTextOutput("受信させたいテキスト");
        response.setMimeType(ContentService.MimeType.TEXT);
        return response;
        */
        //本来はこれでテキストのみを送信する予定だったが、
        //ESP32ではリダイレクト処理がうまくできなかったためContentServiceは利用不可とみた
        var response = HtmlService.createHtmlOutput(`message:${sendtext}:endmessage`);
        //この方法だと無駄にHTMLが書かれるがリダイレクト対策にはこれしかない(と思う)
        //「message:」と「:endmessage」はわかりやすい何か名前を自分で決めてもよい
        return response;
    }
}
サーボ用.ino
//サーボ用。これはどこかのサイトで見かけてコピペしたもの。
#include <WiFi.h> 
#include <WiFiMulti.h> 
WiFiMulti wifiMulti;
#include <HTTPClient.h>
HTTPClient http;

#define SERVO_PIN  26
#define SERVO_CH   0
#define PWM_HZ 50
#define PWM_BIT 16 // 16bit(0~65535)
#define MAX 7800 // 65535 / 20 * 2.4 ≒ 7864 
#define MIN 1700 // 65535 / 20 * 0.5 ≒ 1638

//GASのURL
String url="https://script.google.com/macros/s/hogefuga/exec";

void setup(){
  //ESP32デバイスの初期化とか
  //WiFi接続とか
}

//GASにデータを送信する関数
String sendDataToGAS(String payload) {
  //開始
  String geturl=url+payload; //かなりテキトウな実装
  http.begin(geturl);
  int httpRespCode;
  httpRespCode=http.GET();
  if(httpRespCode!=200){
    return "error";
  }

  String str=http.getString();
  //切断
  http.end();

  //"message:"から":endmessage"までを取得
  int startindex=str.indexOf("message:");
  int endindex=str.indexOf(":endmessage",startindex);

  return str.substring(startindex+8,endindex); //+8というのはmessage:の分の長さ
}

void loop() {
  String payload="?dummy=1";
  String result=sendDataToGAS(payload);
  //resultは"error"とか文字列型の数字とかだったりすると思うからあとは自由にどうぞ
  //例:angle=result.toInt(); みたいにしてから、
  //int duty_cycle  = map(angle, 0, 180, MIN, MAX); 
  //ledcWrite(SERVO_CH, duty_cycle);
}

ちなみに2秒に1回くらいしか受信できません。
僕の知識ではこれが限界でした…

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?