山の中とが池のど真ん中など、ローカルネットワークから隔絶された所の環境測定を行うべく、Arduinoと3GIM( http://a3gs.wiki.fc2.com/ )でセンシングデバイスを構築しました。しかし次に待っていたのはサーバ確保の問題。上の人が動いてくれる気配はないし、自分のを使うのもいろいろと面倒だし、安定性にも自信がないので、代わりにGoogleスプレッドシートを用いてデータ収集を行うことにしました。
GoogleAppsScript(GAS)を用いるメリット
最近のIoTムーブメントおかげで、データをアップロード・ロギングする選択肢はたくさんあります。XivelyとかM2Xとか。でもGASを使いたい。理由は、
- 自前でサーバを用意する必要が無い。
- HTTPSにも対応。多分下手に自分でサーバ立てるよりも安全。
- まあこれは他のサービスにも当てはまりますね。
- 全ての処理をGASで完結できるかも。
- スプレッドシートに表ができてしまえば、もう後は煮るなり焼くなり。
- 無料。
そんなところでしょうか。大体のデータ処理がGoogleのサーバ上で終わってしまうのがありがたいですね。
方法
簡潔に書くとこれだけです。
- スプレッドシートにGASでdoPost(e)メソッドを仕込んで、Webアプリとして公開する。
- Arduino(3GIM)からWebアプリのURLへPOSTメソッドでデータを送りつける。
- 3GIMを用いる場合、ヘッダに
"Content-Type: application/x-www-form-urlencoded"
が必要です。
- 3GIMを用いる場合、ヘッダに
ヘッダを省略するとスプレッドシートに"undefined"のデータが延々とやって来ます。自分はここで詰まりました。
GASのコードはここのコードを改変して使わせて頂きました。(改変というか削っただけ。)
https://mashe.hawksey.info/2011/10/google-spreadsheets-as-a-database-insert-with-apps-script-form-postget-submit-method/
改変後
/*
Copyright 2011 Martin Hawksey
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Original
https://mashe.hawksey.info/2011/10/google-spreadsheets-as-a-database-insert-with-apps-script-form-postget-submit-method/
Customize history
* 2016-04-30 Optimized for 3GIM and Arduino.(by Homimume[http://qiita.com/homimume])
*/
function doPost(e) {
var ss = SpreadsheetApp.openById('[スプレッドシートのID]');
var sheet = ss.getSheetByName("DATA");
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; //read headers
var nextRow = sheet.getLastRow(); // get next row
var cell = sheet.getRange('a1');
var col = 0;
for (i in headers){ // loop through the headers and if a parameter name matches the header name insert the value
if (headers[i] == "Timestamp"){
val = new Date();
} else {
val = e.parameter[headers[i]];
}
cell.offset(nextRow, col).setValue(val);
col++;
}
return ContentService.createTextOutput("PostOK");
}
実は正常にreturnしていなさそうです。実用上問題は無さそうですが・・・。
とりあえずここまで。あまりにも不親切なんで後日加筆するかもです。