GASのdoGet(e){...}
関数でFusionTablesAPIを実行した。
目標
ラズパイのCPU温度を定期的にロギングしてアップロードしたい。
前回
今回
doGet(e)
関数にてFusion Tables APIを実行する。
認証などGUIによる手入力を一切せずに実行できるか確かめる。
結論
ブラウザでの実行なら、個人認証なしでinsert文が実行できた。
ただし、初回のみファイルアクセスへの認証が必要。また、curlなどからの実行は未確認。
対象環境
- Firefox 50.0
- Google Account
- Google Developers Console
- Google Drive
- Google Fusion Tables
- Google Apps Script
Fusion Tables
FusionTablesでテーブルを作成したファイルを作成する。
docid
後でこのファイルのURLパラメータdocid
キーの値をテーブル名として使う。
共有
なお、Fusion Tablesファイルの共有状態はリンクを知っている全員が閲覧できます
状態である。
Google Apps Script
ファイル作成
- Google Driveにアクセスする
- Google Apps Scriptを新規作成する
- 任意のファイル名をつけて保存する
こまかい手順は過去記事を参照。
Googleの拡張サービス
- メニュー→
リソース
→Googleの拡張サービス...
をクリックする
Fusion Tables APIを有効にする。こまかい手順はGASでFusionTablesAPIを叩いてみたを参照。
うっかり忘れて実行すると、以下のようにReferenceError: 「FusionTables」が定義されていません。
と怒られる。
コーディング
- 以下のソースコードを入力する
function doGet(e) { var docId = "01234567890123456789012345678901234567890"; var sql = "INSERT INTO " + docId + " (Timestamp,CpuTemperature)" + " VALUES" + " ('" + e.parameter.TimeStamp.replace(/-/,"/") + "'," + e.parameter.CpuTemperature + ");"; FusionTables.Query.sql(sql); }
公開と実行
- メニュー→
公開
→ウェブアプリケーションとして導入
を選択する
- メニュー→
- アクセスできるユーザを
自分だけ
に設定する 最新のコード
リンクをクリックして実行する
こまかい手順はGASを実行する(HTTP GET)を参照。
実行結果(1回目)
エラー。その操作を実行するには承認が必要です。
とのこと。
やはり出た。承認問題。これをどうにかするのが本題。
承認を要求される条件は何か
GASのdoGet(e)
からFusion Tables APIを使うとその操作を実行するには承認が必要です。
エラーになった。
でも、GASでFusionTablesAPIを叩いてみたときは承認を要求されずに実行できた。select文もinsert文も。このときはmyFunction
関数で実行していた。今回はdoGet(e)
関数で実行した。
doGet(e)
関数だけでは承認を要求されることはない。GASを実行する(HTTP GET)のとき、doGet(e)
関数を実行したが、承認を要求されずに実行できた。今回はFusion Tables APIを使っている。
上記のことから、doGet(e)
関数を使い、なおかつFusion Tables APIを使うとき、承認が必要になるのかもしれない。
回避案
- Apps Scriptの
アプリケーションにアクセスできるユーザー
を全員
にしてみる
誰でもアクセスできるようにしてしまえば、承認なんて不要になるのでは?
結論から言うと、承認は初回のみ必要だった。
公開と実行(2回目)
- メニュー→
公開
→ウェブアプリケーションとして導入
を選択する
- メニュー→
- アクセスできるユーザを
自分だけ
から全員
に変更する 更新
をクリックする承認が必要です
ダイアログが表示される許可を確認
をクリックする{AppsScriptファイル名}が次の許可をリクエストしています
ウインドウが表示される許可
をクリックするウェブアプリケーションとして導入
ダイアログが表示される最新のコード
リンクをクリックして実行する
実行結果(2回目)
Invalid query: Parse error near 'undefined' (line 1, position 101).(行 8、ファイル「コード」)
おそらく、最新のコード
リンクにはURLパラメータがないからエラーになったのだろう。
最新のコード
リンクを右クリックしてリンクのURLをコピー
する。
https://script.google.com/macros/s/{scriptDocId}/dev
の書式だと思う。
そのURLに、ソースコードで定義したURLパラメータを付与する。
https://script.google.com/macros/s/{scriptDocId}/dev?TimeStamp=2000-01-01 23:59:59&CpuTemperature=43210
とする。
- パラメータキーは大文字小文字の区別もするのでソースコードと完全一致させること
- 日付の書式は
yyyy-MM-dd HH:mm:dd
とする(Fusion Tablesのカラム設定と一致させる)
公開と実行(3回目)
- メニュー→
公開
→ウェブアプリケーションとして導入
を選択する
- メニュー→
最新のコード
リンクをクリックして実行する
実行結果(3回目)
doGet(e)
で何もreturnしないとスクリプトが完了しましたが、何も返されませんでした。
というエラーになるらしい。今回は何もreturnしていないので別にいい。
対象のFusionTablesファイルを開いてみる。末尾にデータが挿入されていた!成功!
分析
承認
初回のみ承認画面が必要だったらしい。自分のAppsScriptファイルに全員がアクセス可能であることを、自分で承認することが必要だったということか。
- Fusion Tablesファイルの共有は
リンクを知っている全員が閲覧できます
- Apps Scriptファイルの公開は
全員
ポイント
GAS経由でFunction Tables APIを使い、insertするまでの要点。
ファイル | 要点 |
---|---|
Fusion Tables | メニュー→share →リンクを知っている全員が閲覧できます |
Fusion Tables | SQL文で使うテーブル名はFusion TablesファイルURL内にあるdocid パラメータキー値である |
Apps Script | メニュー→公開 →ウェブアプリケーションとして導入 。アプリケーションにアクセスできるユーザー:全員 |
Apps Script | メニュー→リソース →Googleの拡張サービス... →Fusion TablesをON →Developer ConsoleでFusion Tablesを有効にする |
Apps Script | FusionTables.Query.sql("insert into ..."); でFusion Tablesに対してSQL文を発行する |
Apps Script | function doGet(e) {...} でHTTPのGETに応答する |
Apps Script | e.parameter.{任意のキー名} でdoGet(e) が受け取るURLパラメータを参照する |
Apps Script | return ContentService.createTextOutput("") でdoGet(e) が返すテキストを設定する |
これを把握すれば、自分で任意のWebAPIを作れる上、データベースでデータを管理できる。
課題
GAS経由と直叩きの違いが謎
ただ、Fusion Tables APIに触ってみたときは失敗した。GASを経由せずにAPIKeyを渡したが、insert文はLogin Required
エラーが返ってきた。エラーになったのはGASを経由していないせいか、ブラウザでなくcurlからアクセスしたせいか。
ブラウザ以外から実行できるか
本番はブラウザでなく、curl、python、javascriptなどから実行する予定。その環境でも同じように実行できるか確認する必要がある。
リクエスト上限の詳細が不明
また、勝手な憶測だが、HTTPヘッダのUserAgent次第でリクエスト上限に違いを設けていたりしないだろうか。そんな仕様は見つけていないが、Fusion Tables APIに触ってみたときはすぐにリクエスト上限になってしまった。対して今回はリクエスト上限になっていない。たぶん私の勘違いなり操作ミスなり何なりが原因だと思うが、はっきりさせたい。
こちらによると、1日2万5千リクエストが上限らしい。Query.sql
は1回あたり5リクエスト消費するらしく、1日あたり5千件になるとか。さらに1テーブル1分あたり30件の書き込みが上限らしい。Table.importRows()
で解消できる可能性もあるが、そっちはそっちで内部エラーが出る場合もあるらしい。
公式文書をみてみると、2016/11/28時点でも上記と同じだった。ファイルサイズの上限もあるらしい。1テーブル250MBまで。1アカウントあたり全テーブル1GBまで。
こまかい制限がたくさん出てきた。どうやって運用するかを考える必要がありそう。
所感
ブラウザのロケールバーからGASのdoGet(e)
関数を実行して、Fusion Tables APIを使ってinsert文を発行した。
今回のを自作のプログラムコードから実行できれば目標に近づく。ログインや認証などの手入力なしで可能かどうかが重要。